Compare commits

..

2783 Commits

Author SHA1 Message Date
Dan Brown
fcabf478de Updated version and assets for release v25.11 2025-11-09 12:52:34 +00:00
Dan Brown
8de2c28497 Merge branch 'development' into release 2025-11-09 12:51:26 +00:00
Dan Brown
5bf2d801cf Notifications: Fixed attempted null usage issue where int expected 2025-11-09 11:39:38 +00:00
Dan Brown
1421ba871d Updated translator & dependency attribution before release v25.11 2025-11-09 10:52:09 +00:00
Dan Brown
563828ba52 Updated translations with latest Crowdin changes (#5843) 2025-11-02 14:41:16 +00:00
Dan Brown
d40a68b411 API: Re-ordered routes, Improved navigation
Updated route order to follow some kind of logic.
Updated scrolling sidebar to not be so cut-off in various scenarios.
Added new nav helper to quick jump to specific API models.

Closes #5865
2025-11-02 14:31:08 +00:00
Dan Brown
4a57933cd1 Deps: Updated PHP composer packages 2025-11-02 13:11:38 +00:00
Dan Brown
1df850ea3e Search: Fixed formatting timeout with many term occurrences
For #5863
2025-10-31 15:55:45 +00:00
Dan Brown
7881bddce0 Merge pull request #5860 from BookStackApp/api_image_data_endpoint
API: Added endpoints for reading image data
2025-10-31 13:48:54 +00:00
Dan Brown
02d024aa32 API: Added endpoints for reading image data 2025-10-29 18:17:51 +00:00
Dan Brown
652124abaf Merge pull request #5854 from BookStackApp/efficient_search
Pagable and efficient search
2025-10-29 13:12:52 +00:00
Dan Brown
751934c84a Search: Tested changes to single-table search
Updated filters to use single table where needed.
2025-10-29 12:59:34 +00:00
Dan Brown
3fd25bd03e Search: Added pagination, updated other search uses
Also updated hydrator to be created via injection.
2025-10-28 20:37:41 +00:00
Dan Brown
f0303de2e5 Search: Improved result hydration performance 2025-10-27 18:02:54 +00:00
Dan Brown
0b26573314 Search: Started work to make search result size consistent 2025-10-27 17:23:15 +00:00
Dan Brown
c21c36e2a6 Merge pull request #5850 from BookStackApp/comments_api
API: Started building comments API endpoints
2025-10-24 15:26:55 +01:00
Dan Brown
a949900570 API: Added examples for comments
Tweaked comment repo to avoid returning a lot of extra data on API
update responses.
2025-10-24 15:14:25 +01:00
Dan Brown
9c4a9225af Comments API: Addressed failing tests and static testing 2025-10-24 14:22:53 +01:00
Dan Brown
4627dfd4f7 API: Added comment tree to pages-read endpoint
Includes tests to cover
2025-10-24 10:18:52 +01:00
Dan Brown
fcacf7cacb API: Built out tests for comment API endpoints 2025-10-23 16:52:29 +01:00
Dan Brown
cbf27d70c8 API: Added comment CUD endpoints, drafted tests
Move some checks and made some tweaks to the repo to support consistency
between API and UI.
2025-10-23 10:21:33 +01:00
Dan Brown
3ad1e31fcc API: Added comment-read endpoint, added api docs section descriptions 2025-10-22 18:44:49 +01:00
Dan Brown
082dbc9944 API: Started building comments API endpoints 2025-10-22 14:58:29 +01:00
Dan Brown
abe9c1e5a3 API Docs: Updated link to archived GitHub repo
Closes #5813
2025-10-22 14:29:02 +01:00
Dan Brown
ebf82617b8 Code: Added groovy syntax highlighting
For #5822
2025-10-21 18:34:21 +01:00
Dan Brown
2c81447c9e Deps: Updated PHP deps via composer 2025-10-21 14:47:24 +01:00
Dan Brown
8898647f78 Merge pull request #5846 from BookStackApp/page_image_nullification
Images: Added nulling of image page relation on page delete
2025-10-21 14:46:49 +01:00
Dan Brown
ea6344898f Images: Added nulling of image page relation on page delete 2025-10-21 14:12:55 +01:00
Dan Brown
0bfd79925e Merge pull request #5844 from BookStackApp/user_ids
Updated handling of deleted user ID handling in DB
2025-10-21 13:45:00 +01:00
Dan Brown
efff8700d4 DB: Addressed test issues for user ID changes
Reverted change for activities table so that a record is retained of
past activity, and added a check where the ID may be displayed to ensure
it does not mislead and accidentially reference other, newer users.
2025-10-19 19:52:15 +01:00
Dan Brown
5754acf2fb DB: Updated handling of deleted user ID handling in DB
Updated uses of user ID to nullify on delete.
Added testing to cover deletion of user relations.
Added model factories to support changes and potential other tests.
Cleans existing ID references in the DB via migration.
2025-10-19 19:10:15 +01:00
Dan Brown
4c7d6420ee DB: Aligned entity structure to a common table
As per PR #5800

* DB: Planned out new entity table format via migrations

* DB: Created entity migration logic

Made some other tweaks/fixes while testing.

* DB: Added change of entity relation columns to suit new entities table

* DB: Got most view queries working for new structure

* Entities: Started logic change to new structure

Updated base entity class, and worked through BaseRepo.
Need to go through other repos next.

Removed a couple of redundant interfaces as part of this since we can
move the logic onto the shared ContainerData model as needed.

* Entities: Been through repos to update for new format

* Entities: Updated repos to act on refreshed clones

Changes to core entity models are now done on clones to ensure clean
state before save, and those clones are returned back if changes are
needed after that action.

* Entities: Updated model classes & relations for changes

* Entities: Changed from *Data to a common "contents" system

Added smart loading from builder instances which should hydrate with
"contents()" loaded via join, while keeping the core model original.

* Entities: Moved entity description/covers to own non-model classes

Added back some interfaces.

* Entities: Removed use of contents system for data access

* Entities: Got most queries back to working order

* Entities: Reverted back to data from contents, fixed various issues

* Entities: Started addressing issues from tests

* Entities: Addressed further tests/issues

* Entities: Been through tests to get all passing in dev

Fixed issues and needed test changes along the way.

* Entities: Addressed phpstan errors

* Entities: Reviewed TODO notes

* Entities: Ensured book/shelf relation data removed on destroy

* Entities: Been through API responses & adjusted field visibility

* Entities: Added type index to massively improve query speed
2025-10-18 13:14:30 +01:00
Dan Brown
0838d5ea16 Updated version and assets for release v25.07.3 2025-10-05 15:38:50 +01:00
Dan Brown
449ac40114 Merge branch 'v25-07' into release 2025-10-05 15:37:20 +01:00
Dan Brown
146a6c01cc Merge branch 'v25-07' into development 2025-10-05 15:28:29 +01:00
Dan Brown
f8e4ea82c6 Updated translator & dependency attribution before release v25.07.3 2025-10-05 15:26:37 +01:00
Dan Brown
047195c033 Updated translations with latest Crowdin changes (#5786) 2025-10-05 15:22:37 +01:00
Yugo Takano
a7b30c284c Add crossorigin attribute to manifest link 2025-10-05 15:18:40 +01:00
Dan Brown
c3412d8c1c Deps: Updated PHP package versions 2025-10-05 15:17:16 +01:00
Dan Brown
4db7135231 Updated translations with latest Crowdin changes (#5786) 2025-10-05 15:09:34 +01:00
Dan Brown
009d146185 Merge pull request #5820 from tfnh621/patch-1
Fix PWA manifest access behind authenticated proxies
2025-10-05 15:08:59 +01:00
Yugo Takano
fcef1a7948 Add crossorigin attribute to manifest link 2025-10-02 21:39:22 +09:00
Dan Brown
08dfff05f4 Sponsors: Updated diagrams.net sponsor level 2025-09-11 18:58:26 +01:00
Dan Brown
fc10520e10 Merge pull request #5793 from BookStackApp/role_permission_refactor
Permissions: Use of enum references and RolePermission cleanup
2025-09-10 12:16:40 +01:00
Dan Brown
a70c733f27 Permissions: Cleanup after review of enum implementation PR 2025-09-10 11:36:54 +01:00
Dan Brown
573d692a59 Permissions: Fixed check method to allow enum usage 2025-09-10 10:44:54 +01:00
Dan Brown
419dbadcfd Permissions: Updated use of helpers to use enums
Also added middlware method to Permission enum to allow easier usage
with controller middleware.
2025-09-09 09:48:19 +01:00
Dan Brown
33a0237f87 Permissions: Updated usage of controller methods to use enum 2025-09-08 18:14:38 +01:00
Dan Brown
5fc11d46d5 Permissions: Added enum usage to controller helpers
Also fixed various missing types or spelling/formatting points.
Added down action for role_permission table changes in migration.
2025-09-08 16:15:42 +01:00
Dan Brown
c8716df284 Permissions: Removed unused role-perm columns, added permission enum
Updated main permission check methods to support our new enum.
2025-09-08 15:59:25 +01:00
Dan Brown
1ac74099ca Merge pull request #5790 from BookStackApp/timezones
Timezones: Seperate display timezone and consistency update
2025-09-04 16:36:04 +01:00
Dan Brown
36cb243d5e Timezones: Updated date displays to use consistent formats 2025-09-04 16:11:35 +01:00
Dan Brown
579c1bf424 Timezones: Seperated out store & display timezones to two options 2025-09-04 15:06:58 +01:00
Dan Brown
242b7dfb1b Merge pull request #5785 from BookStackApp/phpstan_level2
PHPstan level 3
2025-09-03 15:53:11 +01:00
Dan Brown
7d1c316202 Maintenance: Updated larastan target level, fixed issues from tests 2025-09-03 15:42:50 +01:00
Dan Brown
318b486e0b Maintenance: Finished changes to meet phpstan level 3 2025-09-03 15:18:49 +01:00
Dan Brown
e05ec7da36 Maintenance: Addressed a range of phpstan level 3 issues 2025-09-03 10:47:45 +01:00
Dan Brown
cee23de6c5 Maintenance: Reached PHPstan level 2
Reworked some stuff around slugs to use interface in a better way.
Also standardised phpdoc to use @return instead of @returns
2025-09-02 16:02:52 +01:00
Dan Brown
1e34954554 Maintenance: Continued work towards PHPstan level 2
Updated html description code to be behind a proper interface.
Set new convention for mode traits/interfaces.
2025-09-02 11:10:47 +01:00
Dan Brown
5ea4e1e935 Maintenance: Removed unused comments text column
Has been redundant and unused for a about a year now.
Closes #4821
2025-09-02 10:20:10 +01:00
Dan Brown
a27ce6e915 Packages: Updated npm packages
Spent way too many hours debugging through issues from jsdom changes.
2025-08-30 22:18:09 +01:00
Dan Brown
64b06bcf61 Packages: Updated predis 2025-08-30 11:47:22 +01:00
Dan Brown
cdbac63b40 Framework: Updated to Laravel 12 2025-08-30 11:10:11 +01:00
Dan Brown
d6296ac7a5 Merge pull request #5749 from BookStackApp/admin_command_updates
Create Admin Command: New Flags
2025-08-30 10:47:14 +01:00
Dan Brown
3131050acd Updated version and assets for release v25.07.2 2025-08-28 17:41:48 +01:00
Dan Brown
c0d2874892 Merge branch 'development' into release 2025-08-28 17:39:31 +01:00
Dan Brown
481f356068 Updated translator & dependency attribution before release v25.07.2 2025-08-28 17:39:10 +01:00
Dan Brown
955837c9aa Packages: Upgraded php deps to latest versions 2025-08-28 15:02:26 +01:00
Dan Brown
c6e35c2e7c Merge pull request #5775 from BookStackApp/lexical_aug25
Lexical: August 2025 fixes
2025-08-28 15:00:16 +01:00
Dan Brown
0436ccfebf Updated translations with latest Crowdin changes (#5759) 2025-08-28 14:59:36 +01:00
Dan Brown
f5da31037d Lexical: Fixed details tests
Updated to use new test pattern while there.
2025-08-28 11:17:18 +01:00
Dan Brown
46613f76f6 Lexical: Added backspace handling for details
Allows more reliable removal of details block on backspace at first
child position with the details block.
2025-08-27 14:09:38 +01:00
Dan Brown
519acaf324 Lexical: Added better selection display for collapisble blocks 2025-08-27 12:51:36 +01:00
Dan Brown
849bc4d6c3 Lexical: Improved nested details interaction
- Set to open by default on insert.
- Updated selection handling not to always fully cascade to lowest
  editable child on selection, so parents can be reliably selected.
- Updated mouse handling to treat details panes like the root element,
  inserting within-details where relevant.
2025-08-26 14:45:15 +01:00
Dan Brown
ee994fa2b7 Testing: Addressed deprecation in test helper
Also updated version in phpunit config
2025-08-25 15:01:13 +01:00
Dan Brown
13a79b3f96 Shelves: Addressed book edits removing non-visible books
Tracks the non-visible existing books on change, to retain as part of
the assigned books sync.
Added test to cover.

For #5728
2025-08-25 14:17:55 +01:00
Dan Brown
7c79b10fb6 Imports: Fixed drawing IDs not being updated in content
Would leave imported content with inaccessible images in many cases (or
wrong references) although the drawing was still being uploaded &
related to the page.
Added test to cover.

For #5761
2025-08-24 14:02:21 +01:00
Dan Brown
5c481b4282 Testing: Added more deprecation output 2025-08-15 12:42:44 +01:00
Dan Brown
9443682ae4 Maintenance: Addressed a range of deprecations
Updated deps to address deprecations fixed in newer Laravel framework
version.
2025-08-15 12:20:35 +01:00
Dan Brown
0311e3d2d7 Readme: Updated sponsor link
Was leading to a 404.
2025-08-14 16:00:46 +01:00
Dan Brown
5940a91809 Updated version and assets for release v25.07.1 2025-08-11 14:43:51 +01:00
Dan Brown
9a4651badb Merge branch 'development' into release 2025-08-11 14:43:13 +01:00
Dan Brown
a50a256939 ZIP Exports: Fixed reference handling for images
Recent changes could mean missed references for images in non-page
locations. This fixes that, and tries to ensure images are used if we
already have a page-based image as part of the ZIP, otherwise ensure we
have a page as part of the export to attach the image to.
2025-08-11 14:19:48 +01:00
Dan Brown
4830248a1e Release: Updated licenses and translator attribution 2025-08-11 13:41:31 +01:00
Dan Brown
1256b30ad4 Updated translations with latest Crowdin changes (#5740) 2025-08-11 13:38:47 +01:00
Dan Brown
777cca76da Deps: Bumped PHP composer deps again 2025-08-11 13:36:06 +01:00
Dan Brown
a2d13124af Testing: Added mail port to testing env options
Prevents conflict with potential user-set option.
For #5755
2025-08-11 13:33:57 +01:00
Dan Brown
bd966ef99e phpstan: Address a range of level 2 issues 2025-08-09 11:09:50 +01:00
Dan Brown
a6b5733ec2 Deps: Updated PHP packages via composer 2025-08-09 10:12:24 +01:00
Dan Brown
e899066e96 Merge branch 'development' of github.com:BookStackApp/BookStack into development 2025-08-08 17:44:40 +01:00
Dan Brown
f4f2435856 Imports: Fixed errors causing user logout on import run
Fixes #5754
2025-08-08 17:43:58 +01:00
Dan Brown
fca4a0563e Merge pull request #5753 from BookStackApp/a11y_menu_updates
A11y: Improved menu tagging
2025-08-08 17:00:07 +01:00
Dan Brown
0bc9ddd780 A11y: Updated other dropdown menus with correct tagging
Made some form improvements at the same time.
2025-08-07 16:37:18 +01:00
Dan Brown
c66f3b2a37 A11y: Improved tagging of profile menu
- Swapped toggle out to actual button.
- Ensured menu items have proper menu item role.
- Added extra roles/labels where is makes sense.
2025-08-07 14:32:20 +01:00
Dan Brown
f36e6fb929 Commands: Updated create admin skip return
Return status for skipped --initial creation will now return 2, so that
it can be identified seperate from a creation and from an error.
2025-08-07 13:16:49 +01:00
Dan Brown
7bc0d54af1 Readme: Swapped codeclimate reference for custom phpmetrics 2025-08-05 22:00:55 +01:00
Dan Brown
2eefbd21c1 Commands: Added testing for initial admin changes
- Also changed first-admin to initial.
- Updated initial handling to not require email/name to be passed, using
  defaults instead.
- Adds missing existing email use check.
2025-08-05 16:43:06 +01:00
Dan Brown
a961552c23 Commands: Updated create admin comment to accept extra flags
Added flags to target changes to the first default admin user, and to
generate a password.
This is related to #4575.
2025-08-05 13:39:30 +01:00
Dan Brown
92d15d9cf2 Updated version and assets for release v25.07 2025-07-30 09:46:37 +01:00
Dan Brown
b06147fef7 Merge branch 'development' into release 2025-07-30 09:45:40 +01:00
Dan Brown
776ec7b9e7 Updated translations with latest Crowdin changes (#5696) 2025-07-30 09:36:34 +01:00
Dan Brown
8aa6bdc8ab Updated translator & dependency attribution before release v25.07 2025-07-30 09:27:17 +01:00
Dan Brown
4ab17157b1 API: Added ZIP export endpoint comments 2025-07-30 09:13:58 +01:00
Dan Brown
6d7ffab115 Deps: Updated PHP composer dependancy versions, fixed test namespaces 2025-07-27 11:24:54 +01:00
Dan Brown
c8cfec96dc Merge pull request #5731 from BookStackApp/lexical_jul25
New WYSIWYG editor changes for July 2025
2025-07-26 10:08:44 +01:00
Dan Brown
d145efb6f6 Lexical: Updated tests after link changes 2025-07-25 14:25:02 +01:00
Dan Brown
c54101c603 Lexical: Updated URL handling, added mouse handling
- Removed URL protocol allow-list to allow any as per old editor.
- Added mouse handling, so that clicks below many last hard-to-escape
  block types will add an empty new paragraph for easy escaping &
  editing.
2025-07-25 13:58:48 +01:00
Dan Brown
865e5aecc9 Lexical: Source code input changes
- Increased default source code view size.
- Updated HTML generation to output each top-level block on its own
  line.
2025-07-24 17:24:59 +01:00
Dan Brown
ae4d1d804a Lexical: Table cell bg and format setting fixes
- Updated table cell background color setting to be stable by
  specifically using the background property over the general styles.
- Updated format shorcuts to be correct header levels as per old editor
  and format menu.
- Updated format changes to properly update UI afterwards.
2025-07-24 16:51:11 +01:00
Dan Brown
5fc19b0edf Lexical: Fixed highlight format action, changed label 2025-07-24 13:48:00 +01:00
Dan Brown
0a73b70b64 Merge pull request #5725 from BookStackApp/md_plaintext
MarkDown Editor: TypeScript Conversion & Plaintext Editor
2025-07-23 15:48:10 +01:00
Dan Brown
2668aae09b TypeScript: Updated compile target, addressed issues 2025-07-23 15:41:55 +01:00
Dan Brown
3b9c0b34ae MD Editor: Fixed plaintext dark styles, updated npm packages 2025-07-23 14:59:26 +01:00
Dan Brown
53f32849a9 MD Editor: Last tests/check over plaintext use/switching 2025-07-23 14:49:41 +01:00
Dan Brown
7ca8bdc231 MD Editor: Added custom textarea undo/redo, updated positioning methods 2025-07-23 12:17:36 +01:00
Dan Brown
6621d55f3d MD Editor: Worked to improve/fix positioning code
Still pending testing. Old logic did not work when lines would wrap, so
changing things to a character/line measuring technique.
Fixed some other isues too while testing shortcuts.
2025-07-22 16:42:47 +01:00
Dan Brown
d55db06c01 MD Editor: Added plaintext/cm switching
Also aligned the construction of the inputs where possible.
2025-07-22 10:34:29 +01:00
Dan Brown
6b4b500a33 MD Editor: Added plaintext input implementation 2025-07-21 18:53:22 +01:00
Dan Brown
5ffec2c52d MD Editor: Updated actions to use input interface 2025-07-21 14:24:51 +01:00
Dan Brown
ec07793cda MD Editor: Started work on input interface
Created implementation for codemirror, yet to use it.
2025-07-21 11:49:58 +01:00
Dan Brown
61adc735c8 MD Editor: Finished conversion to Typescript 2025-07-20 15:05:19 +01:00
Dan Brown
7bbf591a7f MD Editor: Starting conversion to typescript 2025-07-20 12:33:22 +01:00
Dan Brown
61f8d18af5 Changelog: Tweaked spacing, count and element referencing
During review of #5663
2025-07-19 14:53:02 +01:00
Dan Brown
f786d25f2e Merge branch 'enhance-changelog-textarea' of github.com:shresthkapoor7/BookStack into shresthkapoor7-enhance-changelog-textarea 2025-07-19 14:39:57 +01:00
Dan Brown
e62f4426ea Merge pull request #5721 from BookStackApp/zip_export_api_endpoints
API: ZIP Import/Export
2025-07-18 16:34:10 +01:00
Dan Brown
32ba3a591f ZIP Imports: Added API examples, finished testing
Also updated some types on a couple of controllers.
2025-07-18 16:19:14 +01:00
Dan Brown
73025719a4 ZIP Imports: Added API test cases 2025-07-18 14:05:32 +01:00
Dan Brown
d55684531f API: Added zip export tests, reorganised tests
Extracted an extra method into helper for reuse.
2025-07-18 10:58:10 +01:00
Dan Brown
d15eb129b0 API: Initial review pass of zip import/export endpoints
Review of #5592
2025-07-18 09:54:49 +01:00
Dan Brown
3626a2265b Merge branch 'development' of github.com:LM-Nishant/BookStack into LM-Nishant-development 2025-07-18 09:19:32 +01:00
Dan Brown
d13abc7e1d Mail: Removed custom symfony/mailer fork
Moved to standard symfony mailer now that my patches have been
upstreamed. This changes the config to work with the symfony option,
following the same overall logic.
Also updated testing to allow test runs via mulitple custom env options.

Closes #5636
2025-07-15 15:24:31 +01:00
Dan Brown
2442829ef2 Merge branch 'development' of github.com:BookStackApp/BookStack into development 2025-07-14 14:18:51 +01:00
Dan Brown
795b28162a Readme: Added SiteSpeakAI sponsor 2025-07-14 14:18:24 +01:00
Dan Brown
31706ea06b Merge pull request #5689 from BookStackApp/permission_table_locking
Better parallel permission gen handling
2025-07-09 18:02:15 +01:00
Dan Brown
4b9e6042d5 Merge pull request #5676 from BookStackApp/lexical_comments
New WYSIWYG editor for comments & descriptions
2025-07-09 18:01:25 +01:00
Dan Brown
d279b0830b Merge pull request #5685 from BookStackApp/sidebar_rejig
Tri-layout sidebar enhancements
2025-07-09 18:00:56 +01:00
Dan Brown
181ab91b1d Merge pull request #5681 from BookStackApp/parent_tag_classes
Parent tag classes
2025-07-09 17:58:13 +01:00
Dan Brown
841350a937 Updated version and assets for release v25.05.2 2025-07-07 15:01:24 +01:00
Dan Brown
12183bac07 Merge branch 'development' into release 2025-07-07 15:00:35 +01:00
Dan Brown
306f41b6f0 Updated translator & dependency attribution before release v25.05.2 2025-07-07 14:59:07 +01:00
Dan Brown
c1d76d2571 Updated translations with latest Crowdin changes (#5695) 2025-07-07 14:51:45 +01:00
Dan Brown
f83074d50e Languages: Added Nepali as a language option 2025-07-07 14:43:21 +01:00
Dan Brown
2be892be70 Updated translations with latest Crowdin changes (#5659) 2025-07-07 14:35:19 +01:00
Dan Brown
c934b9319f PHP: Updated composer packages
Main intent was to get latest ssddanbrown/htmldiff version so better
handle non-ascii languages.
2025-07-07 14:24:04 +01:00
Dan Brown
35a51197ce Perms: Fixed some issues made when adding transactions 2025-07-06 22:52:06 +01:00
Dan Brown
47fd578edb Perms: Added transactions around permission effecting actions 2025-07-02 22:25:59 +01:00
Dan Brown
add091305c Perms: Removed entity perm regen on general update
Should not be needed here as this is not directly used for information
which should impact permissions.
Been through uses to ensure that this is the case.
2025-07-02 12:15:25 +01:00
Dan Brown
3d017594a8 Opensearch: Fixed XML declaration when php short tags enabled
For #5673
2025-07-01 11:29:16 +01:00
Dan Brown
0dcb2ec78c Layout: Converted tri-layout component to ts 2025-06-30 15:36:27 +01:00
Dan Brown
9186e77d27 Layout: Added scroll fade to the sidebars 2025-06-30 14:10:48 +01:00
Dan Brown
6045aff33a Layout: Improved sidebar sizing, and dropdown consideration
- Updated tri-layout sidebars to have less padding and to avoid cutting
  off content when in single-sidebar mode.
- Updated dropdown handling to consider the parent scroll container when
  deciding to drop upwards, to help prevent cut-off.
2025-06-30 13:19:45 +01:00
Dan Brown
dca9765d5d Customization: Added parent tag classes
For #5217
2025-06-28 22:27:28 +01:00
Dan Brown
a37d0c57dc Tests: Updated comment test to account for new editor usage 2025-06-27 10:33:28 +01:00
Dan Brown
054475135a Lexical: Added some styling and tweaks for basic editors 2025-06-27 10:19:45 +01:00
Dan Brown
02a35b6db4 Lexical: Added new WYSIWYG to chapter/book/shelf descriptions 2025-06-26 11:00:17 +01:00
Dan Brown
b80992ca59 Comments: Switched to lexical editor
Required a lot of changes to provide at least a decent attempt at proper
editor teardown control.
Also updates HtmlDescriptionFilter and testing to address issue with bad
child iteration which could lead to missed items.
Renamed editor version from comments to basic as it'll also be used for
item descriptions.
2025-06-25 14:16:01 +01:00
Dan Brown
c606970e38 Lexical: Started comment implementation
Refactors some UI and toolbar code for better abstract use across editor
versions.
2025-06-24 17:47:53 +01:00
Dan Brown
dfeca246a0 Merge pull request #5668 from bumperbox/patch-1
CommentDisplayTest correct namespace
2025-06-23 11:57:57 +01:00
bumperbox
3476d83ecc CommentDisplayTest correct namespace
Class Entity\CommentDisplayTest located in ./tests/Entity/CommentDisplayTest.php does not comply with psr-4 autoloading standard (rule: Tests\ => ./tests). Skipping.
2025-06-23 09:31:39 +12:00
Shresth Kapoor
3617ab1540 Enhance changelog input to textarea with character counter 2025-06-18 20:10:20 -04:00
Dan Brown
e65b4b63a2 Updated version and assets for release v25.05.1 2025-06-17 15:30:40 +01:00
Dan Brown
7cac3f4780 Merge branch 'development' into release 2025-06-17 15:29:46 +01:00
Dan Brown
c4839c783a Updated translator & dependency attribution before release v25.05.1 2025-06-17 15:29:12 +01:00
Dan Brown
a5751a584c Updated translations with latest Crowdin changes (#5637) 2025-06-17 15:16:25 +01:00
Dan Brown
f518a3be37 Search: Updated indexer to handle non-breaking-spaces
Related to #5640
2025-06-17 14:00:13 +01:00
Dan Brown
0208f066c5 Comments: Fixed update notification text
For #5642
2025-06-17 13:42:25 +01:00
Dan Brown
2d0461b63a Merge pull request #5653 from BookStackApp/v25-05-1-lexical
Lexical Fixes for v25.05.1
2025-06-17 13:36:55 +01:00
Dan Brown
b913ae703d Lexical: Media form improvements
- Allowed re-editing of existing embed HTML code.
- Handled "src" form field when video is using child source tags.
2025-06-15 20:00:28 +01:00
Dan Brown
1611b0399f Lexical: Added a media toolbar, improved toolbars and media selection
- Updated toolbars to auto-refresh ui if it attempts to update targeting
  a DOM element which no longer exists.
- Removed MediaNode dom specific click handling which was causing
  selection issues, and did not seem to be needed now.
2025-06-15 15:22:27 +01:00
Dan Brown
8d4b8ff4f3 Lexical: Fixed media resize handling
- Updating height/width setting to clear any inline CSS width/height
  rules which would override and prevent resizes showing. This was
  common when switching media from old editor.
  Added test to cover.
- Updated resizer to track node so that it is retained & displayed
  across node DOM changes, which was previously causing the
  resizer/focus to disappear.
2025-06-15 13:55:42 +01:00
Dan Brown
77a88618c2 Lexical: Fixed double-bold text, updated tests
Double bold was due to text field exporting wrapping the output in <b>
tags when the main tag would already be strong.
2025-06-14 14:50:10 +01:00
Dan Brown
8b062d4795 Lexical: Fixed strange paragraph formatting behaviour
Formatting was not persisted on empty paragraphs, and was instead based
upon last format encountered in selection.
This was due to overly-hasty removal of other formatting code, which
this got caught it.
Restored required parts from prior codebase.

Also updated inline format button active indicator to reflect formats
using the above, so correct buttons are shown as active even when just
in an empty paragraph.
2025-06-13 19:40:13 +01:00
Dan Brown
717b516341 Lexical: Made table resize handles more efficent & less buggy
Fine mouse movement and handles will now only be active when actually
within a table, otherwise less frequent mouseovers are used to track if
in/out a table.
Hides handles when out of a table, preventing a range of issues with
stray handles floating about.
2025-06-13 16:38:53 +01:00
Dan Brown
fda242d3da Lexical: Fixed tiny image resizer on image insert
Added specific focus on image insert, and updated resize handler to
watch for load events and toggle a resize once loaded.
2025-06-13 15:58:59 +01:00
Dan Brown
aac547934c Deps: Bumped composer php package versions 2025-06-13 15:28:11 +01:00
Dan Brown
92cd11d105 Updated version and assets for release v25.05 2025-05-31 14:27:44 +01:00
Dan Brown
13115ace84 Merge branch 'development' into release 2025-05-31 14:26:04 +01:00
Dan Brown
5c9b90ea0d Merge branch 'development' of github.com:BookStackApp/BookStack into development 2025-05-31 12:36:21 +01:00
Dan Brown
074f193e2f Updated translation attribution and licenses before release 2025-05-31 12:35:47 +01:00
Dan Brown
7f2604c8e8 Updated translations with latest Crowdin changes (#5622) 2025-05-31 12:15:16 +01:00
Dan Brown
b71b2a4376 Cleanup: Updated deps, fixed test, update issue templates
Also removed some unused imports.
2025-05-31 12:11:00 +01:00
Dan Brown
68df43e5a8 Merge pull request #5627 from BookStackApp/lexical_20250525
Lexical Editor: Further fixes
2025-05-28 22:53:03 +01:00
Dan Brown
c5ca865723 Lexical: Updated WYSIWYG editor status from alpha to beta 2025-05-28 22:52:09 +01:00
Dan Brown
b862f12a50 Lexical: Further improvements to table selection and captions
- Fixed errors with selection and range handling due to captions
  existing.
- Updated TableNode change handling to update existing DOM instead of
  re-creating, which avoids breaking an attached selection helper.
  - To support, Added function to handle node change detection and apply
    relevant dom updates for common properties.
2025-05-28 22:47:39 +01:00
Dan Brown
b0f8b11054 Comments: Fixed tab focus change & button placement on form usage
Fixes issue of tabs jumping back to active comments when stopping a
reply to an archived comment.
Fixes button placement looking odd due to wrong location and differing
styles depending on interaction path.
2025-05-28 22:00:24 +01:00
Dan Brown
7650ebf2f9 Deps: Updated composer/npm packages, fixed test namespace 2025-05-27 15:53:46 +01:00
Dan Brown
d9ea52522e Lexical: Fixed issues with recent changes 2025-05-26 19:06:36 +01:00
Dan Brown
2e718c12e1 Lexical: Changed table esacpe handling
Avoids misuse of selectPrevious/Next as per prior commit which was then
causing problems elsewhere, and is probably best to avoid creation in
those select methods anyway.
2025-05-26 18:47:51 +01:00
Dan Brown
a43a1832f5 Lexical: Added image insert via image link paste
Specifically added to align with existing TinyMCE behaviour which was
used by some users based upon new editor feedback.
2025-05-26 18:02:53 +01:00
Dan Brown
c4f7368c1c Lexical: Fixed table column resizing changes not appearing
Also fixed some resizer zindex issues.
2025-05-26 15:19:11 +01:00
Dan Brown
2a32475541 Lexical: Made a range of selection improvements
Updated up/down handling to create where a selection candidate does not
exist, to apply to a wider scenario via the selectPrevious/Next methods.

Updated DOM selection change handling to identify single selections
within decorated nodes to select them in full, instead of losing
selection due to partial selection of their contents.

Updated table selection handling so that our colgroups are ignored for
internal selection focus handling.
2025-05-26 14:51:03 +01:00
Dan Brown
1243108e0f Lexical: Updated dropdown handling to match tinymce behaviour
Now toolbars stay open on mouse-out, and close on other toolbar open,
outside click or an accepted action.
To support:
- Added new system to track and manage open dropdowns.
- Added way for buttons to optionally emit events upon actions.
- Added way to listen for events.
- Used the above to control when dropdowns should hide on action, since
  some dont (like overflow containers and split dropdown buttons).
2025-05-25 16:28:42 +01:00
Dan Brown
3280919370 Lexical: Improved diagram selection and keyboard usage
Fixes issues where drawings could not be removed via backspace or
delete.
2025-05-25 13:21:13 +01:00
Dan Brown
d149b809b1 Merge pull request #5626 from BookStackApp/rubentalstra-development
Review of #5429, OIDC avatar fetching
2025-05-24 18:14:18 +01:00
Dan Brown
eb47e11916 Avatars: Added redirect handling image fetching
Up to 3 times.
Can be needed based upon testing with Auth0.
Should be fine as long as it's something clearly documented.
Added test to cover.
2025-05-24 18:07:25 +01:00
Dan Brown
9d6bc1ad4d Testing: Updated tests to account for recent page redirect changes 2025-05-24 16:47:01 +01:00
Dan Brown
30bf0ce632 OIDC: Updated avatar fetching to run on each login
But only where the user does not already have an avatar assigned.
This aligns with the LDAP avatar fetching logic.
2025-05-24 16:34:36 +01:00
Dan Brown
b64c9b31d5 OIDC: Added testing coverage for picture fetching 2025-05-24 14:36:36 +01:00
Dan Brown
f9dbbe5d70 OIDC: Updated picture fetch implementation during review
Review of #5429
2025-05-24 14:02:37 +01:00
Dan Brown
05f7f4cb17 Merge branch 'development' of github.com:rubentalstra/BookStack into rubentalstra-development 2025-05-24 13:28:23 +01:00
Dan Brown
454b152b95 Pages: Redirect user to view if they can't edit
For #5568
2025-05-24 12:05:17 +01:00
Dan Brown
b29fe5c46d Merge pull request #5625 from BookStackApp/avif_images
AVIF image support
2025-05-23 17:30:24 +01:00
Dan Brown
131ac29df4 Images: Added testing to cover animated avif handling 2025-05-23 17:19:34 +01:00
Dan Brown
3a9d18a6cd Images: Added base avif support
Includes handling for animated avif images like apng.
2025-05-23 16:12:03 +01:00
Dan Brown
59e2c5e52a Merge pull request #5607 from BookStackApp/system_info_endpoint
API: System info endpoint
2025-05-22 17:31:32 +01:00
Dan Brown
d29b14ebfd Merge pull request #5584 from BookStackApp/content_comments
Content Comments
2025-05-22 16:58:36 +01:00
Dan Brown
73f9834e6f Updated version and assets for release v25.02.5 2025-05-17 12:16:55 +01:00
Dan Brown
3afe855156 Merge branch 'development' into release 2025-05-17 12:14:51 +01:00
Dan Brown
cdd446ac73 Updated translations with latest Crowdin changes (#5608) 2025-05-17 12:04:25 +01:00
Dan Brown
1dd1024eba Merge pull request #5609 from BookStackApp/5605-folder-permissions
Images: Updated local disk to have open dir perms
2025-05-17 11:49:44 +01:00
Dan Brown
752cfe2f67 CLI: Updated CLI with fixes
- Updated php packages
- Added escaping for mysql options
2025-05-17 11:47:33 +01:00
Dan Brown
25baaa8189 Deps: Updated composer packages 2025-05-17 11:40:58 +01:00
Dan Brown
d2d0331782 Readme: Replaced discord/mastodon links, reformatted badges 2025-05-14 23:15:46 +01:00
Dan Brown
8121418e18 Readme: Added phamos as sponsor 2025-05-14 22:35:59 +01:00
Dan Brown
5ab31a8191 Images: Updated local disk to have open dir perms
Closes #5605
2025-05-14 18:15:20 +01:00
Dan Brown
0e69ab1938 API: Added test to cover system info endpoint 2025-05-13 20:46:11 +01:00
Dan Brown
058007109e API: Added system read endpoint
Standardised logic for reading app version to its own static class.
2025-05-13 20:38:08 +01:00
Dan Brown
32b29fcdfc Comments: Fixed pointer display, Fixed translation test 2025-05-13 12:03:15 +01:00
Dan Brown
8f92b6f21b Comments: Fixed a range of TS errors + other
- Migrated toolbox component to TS
- Aligned how custom event types are managed
- Fixed PHP use of content_ref where not provided
2025-05-12 15:31:55 +01:00
Dan Brown
62f78f1c6d Comments: Split tests, added extra archive/reference tests 2025-05-12 14:26:09 +01:00
Dan Brown
f8c0aaff03 Comments: Checked content/arhived comment styles in dark mode
Also added default non-clickable styles for scenarios for references
which don't have an active content link.
2025-05-09 14:17:04 +01:00
Dan Brown
a27df485bb Comments: Fixed display, added archive list support for editor toolbox 2025-05-09 12:14:28 +01:00
Dan Brown
bfde896f0b Updated version and assets for release v25.02.4 2025-05-08 16:01:45 +01:00
Dan Brown
1cdc0a7a3d Merge branch 'development' into release 2025-05-08 15:57:02 +01:00
Dan Brown
3e99ce4098 Deps: Updated PHP packages
Mainly to update termwind which was causing issues for users on Arch
where a more recent libxml version was in use.
2025-05-08 15:53:25 +01:00
Dan Brown
d19b86640b Updated version and assets for release v25.02.3 2025-05-05 18:32:39 +01:00
Dan Brown
2936ba609b Merge branch 'development' into release 2025-05-05 18:20:31 +01:00
Dan Brown
ce1e20501c Updated translator & dependency attribution before release v25.02.3 2025-05-05 18:14:18 +01:00
Dan Brown
295532fa7a Deps: Updated PHP packages 2025-05-05 18:09:49 +01:00
Dan Brown
642ba668b1 Merge pull request #5601 from BookStackApp/file_permissions
Images: Changed how new image permissions are set
2025-05-05 12:54:40 +01:00
Dan Brown
4f36cdd757 Updated translations with latest Crowdin changes (#5566) 2025-05-05 12:24:12 +01:00
Dan Brown
8821844c4a Exports: Fixed CSS file BOM mark breaking CSS variables in exports
Adds a dummy CSS rule to break as the first rule, instead of our
:root variables.
Fixes #5576
2025-05-05 12:21:32 +01:00
Dan Brown
1262083fcf Images: Changed how new image permissions are set
Removed default public visibility for images at the driver level,
leaving only doing this as a specific action in the logic.
Added try/catch around permission setting so that
permission-incompatible environments won't fatally fail, but instead
log a warning.

Tested via a google cloud storage bucket FUSE mount, mounted under another
user but with open 777 permissions.

Related to #5269
2025-05-03 20:30:50 +01:00
Dan Brown
c82fa33210 Comments: Further range of content reference ux improvements
- Added reference indicator to comment create form.
  - Added remove action.
- Extracted reference text to translations.
- Changed reference hash to be text-based instead of HTML based.
- Added reference display for newly added comments.
- Handled reference marker delete on comment delete.
2025-05-01 17:22:12 +01:00
Dan Brown
15c79c38db Comments: Addressed a range of edge cases and ux issues for references
Handles only display and handling references when they're in the active
tab, while handling proper removal when made not visible.
2025-05-01 16:33:42 +01:00
Dan Brown
e7dcc2dcdf Comments: Moved to tab UI, Converted tabs component to ts 2025-04-30 17:42:09 +01:00
Dan Brown
099f6104d0 Comments: Started archive display, created mode for tree node 2025-04-28 20:09:18 +01:00
Dan Brown
8bdf948743 Comments: Added archive endpoints, messages, Js actions and tests 2025-04-28 15:37:09 +01:00
Dan Brown
e8f44186a8 Comments: Split out page comment reference logic to own component
Started support for editor view.
Moved comment elements to be added relative to content area instad of
specific target reference element.
Added relocating on screen size change.
2025-04-27 16:51:24 +01:00
Dan Brown
ecda4e1d6f Comments: Added reference marker to comments 2025-04-26 21:05:54 +01:00
nchoudhary@logicmines.in
64da80cbf4 added routes for zip export 2025-04-25 13:00:06 +05:30
nchoudhary@logicmines.in
5fa728f28a Develop functionality to import ZIP files. Create an API controller and define a route entry for handling the import process. Implement logic to read the list of files within the ZIP, process the directory structure, and automatically create associated pages, chapters, and books based on the ZIP file's contents. 2025-04-25 12:48:34 +05:30
nchoudhary@logicmines.in
c61ce8dee4 Implement functionality to export a book, along with its pages and chapters, as a ZIP file. 2025-04-25 12:45:09 +05:30
Dan Brown
f656a82fe7 Comments: Styled content comments & improved interaction 2025-04-24 13:21:23 +01:00
Dan Brown
5bfba281fc Comments: Started inline comment display windows 2025-04-21 14:04:41 +01:00
Dan Brown
18ede9bbd3 Comments: Added inline comment marker/highlight logic 2025-04-19 14:07:52 +01:00
Dan Brown
2e7544a865 Comments: Converted comment component to TS 2025-04-19 12:46:47 +01:00
Dan Brown
5e3c3ad634 Comments: Added back-end content reference handling
Also added archived property, to be added.
2025-04-18 21:13:49 +01:00
Dan Brown
add238fe9f Comments & Pointer: Converted components to typescript
Made changes for dom and translation services for easier usage
considering types.
trans_choice updated to allow default count replacement data as per
Laravel's default behaviour.
2025-04-18 20:42:56 +01:00
Dan Brown
8d159f77e4 Comments: Started logic for content references
Adds button for comments to pointer.
Adds logic to generate a content reference point.
2025-04-18 15:01:57 +01:00
Dan Brown
573a2dd22a Updated version and assets for release v25.02.2 2025-04-02 17:32:58 +01:00
Dan Brown
b55cc803d3 Merge branch 'development' into release 2025-04-02 17:31:14 +01:00
Dan Brown
fa566f156a Updated translator & dependency attribution before release v25.02.2 2025-04-02 17:30:43 +01:00
Dan Brown
78a0a2f519 Merge pull request #5558 from BookStackApp/lexical_round3
Lexical Fixes: Round 3
2025-04-02 17:23:38 +01:00
Dan Brown
42cbd6adef Updated translations with latest Crowdin changes (#5537) 2025-04-02 17:19:34 +01:00
Dan Brown
6117349893 Deps: Updated composer packages 2025-04-02 15:30:31 +01:00
Dan Brown
1256320c72 Merge branch 'bernardo-campos/development' into development 2025-04-02 15:18:31 +01:00
Dan Brown
1ba0d26fdd Sort Rules: Updated name comparison to not ignore non-ascii chars
Related to #5550 and #5542
2025-04-02 15:17:17 +01:00
Dan Brown
802f69cf35 Comments: Fixed missing comment timestamps
Due to deleted code during Laravel 11 upgrade.
Added test to cover.
Closes #5555
2025-03-30 17:36:48 +01:00
Dan Brown
bb44334224 Lexical: Added tests to cover recent changes
Also updated list tests to new test process.
2025-03-28 18:29:00 +00:00
Dan Brown
9bfcadd95f Lexical: Improved navigation around images/media
- Added specific handling to move/insert-up/down on arrow press.
- Prevented resize overlay from interrupting image node focus.
2025-03-28 14:30:03 +00:00
Dan Brown
62c8eb3357 Lexical: Made list selections & intendting more reliable
- Added handling to not include parent of top-most list range selection
  so that it's not also changed while not visually part of the
  selection range.
- Fixed issue where list items could be left over after unnesting, due
  to empty checks/removals occuring before all child handling.
- Added node sorting, applied to list items during nest operations so
  that selection range remains reliable.
2025-03-27 17:49:48 +00:00
Dan Brown
c03e44124a Lexical: Fixed task list parsing
Updated list DOM parsing to properly consider task list format set by
other MD/WYSIWYG editors.
2025-03-27 14:56:32 +00:00
Dan Brown
5c6671b3bf Lexical: Fixed issues with content not saving
Found that saving via Ctrl+Enter did not save as logic to load editor
output into form was bypassed, which this fixes by ensuring submit
events are raised during for this shortcut.

Submit handling also gets a timeout added since, at least in FF,
requestSubmit did not re-submit a form while in a submit event.
2025-03-27 14:13:18 +00:00
Bernardo Campos
abe7467ae5 Fix issue BookStackApp#5542 Sorting by name 2025-03-23 12:29:29 -03:00
Dan Brown
304ade418e Updated version, assets, and checksums for release v25.02.1 2025-03-16 12:47:19 +00:00
Dan Brown
997931c42f Merge branch 'development' into release 2025-03-16 12:45:08 +00:00
Dan Brown
0ec0913846 Merge branch 'development' of github.com:BookStackApp/BookStack into development 2025-03-16 12:44:42 +00:00
Dan Brown
e980564fd6 Updated translator & dependency attribution before release v25.02.1 2025-03-16 12:44:29 +00:00
Dan Brown
8a9215ecad Updated translations with latest Crowdin changes (#5505) 2025-03-16 12:25:53 +00:00
Dan Brown
304a1d8f91 Dependancies: Updated PHP composer deps 2025-03-16 12:04:19 +00:00
Dan Brown
dfbc78947f Revisions: Hid changes link for oldest revision
Just as a UX improvement to help avoid confusion, as the whole content
will be changes for this revision.

For #5454
2025-03-16 12:00:54 +00:00
Dan Brown
4f5ad171ac Config: Updated DB host to handle ipv6
Can be set via the square bracket format.
For #5464
2025-03-15 20:32:57 +00:00
Dan Brown
94b1cffa2d System CLI: Updated with new version
As per https://codeberg.org/bookstack/system-cli/pulls/21
dev/checksums folder added to support this new system.

Related to #161
2025-03-11 23:52:01 +00:00
Dan Brown
268e353431 Updated version and assets for release v25.02 2025-02-26 14:30:52 +00:00
Dan Brown
b491b5fbca Merge branch 'development' into release 2025-02-26 14:30:17 +00:00
Dan Brown
13dae24cbe Testing: Fixed issues during pre-release testing
- Updated locale list
- Fixed new name sorting not being case insensitive
- Updated license test to account for changed deps
2025-02-26 14:19:03 +00:00
Dan Brown
6211d6bcfc Updated translations with latest Crowdin changes (#5409) 2025-02-26 13:51:51 +00:00
Dan Brown
a384599cfa Meta: Updated licenses and translation attribution pre v25.02 2025-02-26 13:44:56 +00:00
Dan Brown
dca14feaaa Sorting: Fixes during testing of sort rules
- Fixed name numeric sorting not working as expected due to bad
  comparison.
- Added name numeric desc operation option.
- Added test to ensure each operating has a comparison function.
2025-02-24 16:58:59 +00:00
Dan Brown
d7ccb3ce6a Sorting: Updated text for sort rules
Removes 'Set' wording and notes application to books on change.
2025-02-23 14:41:26 +00:00
Dan Brown
6548ea4a12 JS: Upated npm deps, upgraded eslint, new eslint config
Upgraded eslint to 11, removed incompatible airbnb config as part of
process. ESlint config now in its own file.
2025-02-23 11:55:09 +00:00
Dan Brown
c3a1fabbf0 Deps & Tests: Updated PHP deps, fixed test namespaces 2025-02-23 11:30:10 +00:00
Dan Brown
d2542d6265 Merge pull request #5491 from BookStackApp/deprecations
Addressing PHP 8.4 Deprecations
2025-02-23 11:23:35 +00:00
Dan Brown
0e343c408f Merge pull request #5463 from BookStackApp/v24-12
v24-12 branch changes
2025-02-23 11:22:12 +00:00
Dan Brown
5c78f8352e Styles: Fixed breakpoint overlap
Alters common breakpoint utilities to not overlap at breakpoints which
would cause broken layout at those points.
For #5396
2025-02-23 11:19:11 +00:00
Dan Brown
35b45a2b8d LDAP: Fixed php type error when no cn provided for user
Changes default fallback for name to first DN part, otherwise the whole
DN, rather than leave as null which was causing a type error.

For #5443
2025-02-20 13:06:49 +00:00
Dan Brown
5050719ea3 PHP: Updated DOMPDF version 2025-02-17 13:37:58 +00:00
Dan Brown
5508c171db PHP: Addressed 8.4 deprecations within app itself 2025-02-17 12:45:37 +00:00
Dan Brown
3b4d3430a5 Tests: Updated failing license test 2025-02-17 12:07:23 +00:00
Dan Brown
213a86e3c0 Merge pull request #5415 from BookStackApp/more_lexical_fixes
Further Lexical Fixes
2025-02-16 15:28:55 +00:00
Dan Brown
2b746425c9 Lexical: Fixed code in lists, removed extra old alignment code
Code in lists could throw error on parse due to inner <code> tag being
parsed but not actually used within a <pre>, so this updates the
importDOM to disregard childdren for code blocks.

This also improves the invariant implementation to not be so
dev/debugger based, and to include vars in the output.
2025-02-16 15:09:33 +00:00
Dan Brown
5c15f4add2 Translations: Fixed a couple of errors in sorting en words 2025-02-16 11:27:49 +00:00
Dan Brown
92ad81429f Merge pull request #5488 from BookStackApp/search_index_updates
Search index improvements
2025-02-14 19:39:08 +00:00
Dan Brown
f1b8e857bf Searching: Added test for guillemets
To cover #5475
2025-02-14 19:30:25 +00:00
Dan Brown
c291d27c19 Merge branch 'inv-hareesh/development' into search_index_updates 2025-02-14 19:25:59 +00:00
Dan Brown
f4449928f8 Searching: Added custom tokenizer that considers soft delimiters.
This changes indexing so that a.b now indexes as "a", "b" AND "a.b"
instead of just the first two, for periods and hypens, so terms
containing those characters can be searched within.

Adds hypens as a delimiter - #2095
2025-02-14 19:01:51 +00:00
Dan Brown
45a15b4792 Searching: Split out search tests into their own dir 2025-02-14 13:24:39 +00:00
Dan Brown
2291d78382 Merge pull request #5470 from Silverlan/patch-1
Fix incorrect condition for displaying new books section
2025-02-12 18:14:28 +00:00
Dan Brown
7901ca9e6b Meta: Updated dev version and sponsor link 2025-02-11 15:52:35 +00:00
Dan Brown
a7de251876 Merge pull request #5457 from BookStackApp/sort_sets
Sort rules
2025-02-11 15:41:19 +00:00
Dan Brown
7bd89316bc Sorting: Updated sort set command, Changed sort timestamp handling
- Renamed AssignSortSetCommand to AssignSortRuleCommand, updated
  contents and testing.
- Updated sorting operations to not update timestamps if only priority
  is changed.
2025-02-11 15:29:16 +00:00
Dan Brown
b9306a9029 Sorting: Renamed sort set to sort rule
Renamed based on feedback from Tim and Script on Discord.
Also fixed flaky test
2025-02-11 14:36:25 +00:00
Dan Brown
a208c46b62 Sorting: Covered sort set management with tests 2025-02-10 17:19:49 +00:00
Dan Brown
a65701294e Sorting: Split out test class, added book autosort tests
Just for test view, actual functionality of autosort on change still
needs to be tested.
2025-02-10 13:33:10 +00:00
Dan Brown
69683d50ec Sorting: Added tests to cover AssignSortSetCommand 2025-02-09 23:24:36 +00:00
Dan Brown
37d020c083 Sorting: Addded command to apply sort sets 2025-02-09 17:44:24 +00:00
Dan Brown
ec79517493 Sorting: Added auto sort option to book sort UI
Includes indicator on books added to sort operation.
2025-02-09 15:16:18 +00:00
inv-hareesh
d938565839 Fix search issue for words inside Guillemets (« ») without spaces 2025-02-07 08:59:36 +05:30
Dan Brown
ccd94684eb Sorting: Improved sort set display, delete, added action on edit
- Changes to a sort set will now auto-apply to assinged books (basic
  chunck through all on save).
- Added book count indicator to sort set list items.
- Deletion now has confirmation and auto-handling of assigned
  books/settings.
2025-02-06 14:58:08 +00:00
Dan Brown
103a8a8e8e Meta: Updated sponsor list, licence year and readme 2025-02-05 21:17:48 +00:00
Dan Brown
c13ce18837 Sorting: Added book autosort logic 2025-02-05 16:52:20 +00:00
Dan Brown
7093daa49d Sorting: Connected up default sort setting for books 2025-02-05 14:33:46 +00:00
Dan Brown
b897af2ed0 Sorting: Finished main sort set CRUD work 2025-02-04 20:11:35 +00:00
Dan Brown
d28278bba6 Sorting: Added sort set form manager UI JS
Extracted much code to be shared with the shelf books management UI
2025-02-04 15:14:22 +00:00
Silverlan
12cc2f0689 Fix incorrect condition for displaying new books section 2025-02-03 19:01:08 +01:00
Dan Brown
bf8a84a8b1 Sorting: Started sort set routes and form 2025-02-03 16:48:57 +00:00
Dan Brown
4f5f7c10b1 Thumbnails: Fixed thumnail orientation
Prevents double rotation caused from both our own orientation handling
upon that invervention was auto-applying since v3.

Fixes #5462
2025-01-31 21:29:38 +00:00
Dan Brown
a34023f715 Sorting: Added content misses from last commit, started settings 2025-01-30 17:49:19 +00:00
Dan Brown
b2ac3e0834 Sorting: Added SortSet model & migration 2025-01-29 17:34:07 +00:00
Dan Brown
5b0cb3dd50 Sorting: Extracted URL sort helper to own class
Was only used in one place, so didn't make sense to have extra global
helper clutter.
2025-01-29 17:02:34 +00:00
Dan Brown
ac0cd9995d Sorting: Reorganised book sort code to its own directory 2025-01-29 16:40:11 +00:00
Dan Brown
7e03a973d8 Lexical: Ran a deeper check on translation use 2025-01-27 16:40:41 +00:00
Dan Brown
d89a2fdb15 Lexical: Added media src conversions
Only actuall added YT in the end.
Google had changed URL scheme, and Vimeo seems to just be something else
now, can't really browse video pages like before.
2025-01-27 14:28:27 +00:00
Dan Brown
958b537a49 Lexical: Linked table form to have caption toggle option 2025-01-22 20:39:15 +00:00
Dan Brown
8a66365d48 Lexical: Added support for table caption nodes
Needs linking up to the table form still.
2025-01-22 12:54:13 +00:00
Talstra Ruben SRSNL
da82e70ca3 Add optional OIDC avatar fetching from the “picture” claim 2025-01-20 17:21:46 +01:00
Dan Brown
04cca77ae6 Lexical: Added color picker/indicator to form fields 2025-01-18 11:12:43 +00:00
Dan Brown
c091f67db3 Lexical: Added color format custom color select
Includes tracking of selected colors via localstorage for display.
2025-01-17 11:17:51 +00:00
Dan Brown
7f5fd16dc6 Lexical: Added some general test guidance
Just to help remember the general layout/methods that we've added to
make testing easier.
2025-01-15 14:31:09 +00:00
Dan Brown
0d1a237f81 Lexical: Fixed auto-link issue
Added extra test helper to check the editor state directly via string
notation access rather than juggling types/objects to access deep
properties.
2025-01-15 14:15:58 +00:00
Dan Brown
786a434c03 Merge pull request #5405 from BookStackApp/public_theme_files
Theme System: Public serving of files
2025-01-14 14:56:43 +00:00
Dan Brown
25c4f4b02b Themes: Documented public file serving 2025-01-14 14:53:10 +00:00
Dan Brown
481580be17 Themes: Added testing and better mime sniffing for public serving
Existing mime sniffer wasn't great at distinguishing between plaintext
file types, so added a custom extension based mapping for common web
formats that may be expected to be used with this.
2025-01-13 16:51:07 +00:00
Dan Brown
593645acfe Themes: Added route to serve public theme files
Allows files to be placed within a "public" folder within a theme
directory which the contents of will served by BookStack for access.

- Only "web safe" content-types are provided.
- A static 1 day cache time it set on served files.

For #3904
2025-01-13 14:34:44 +00:00
Dan Brown
b9751807e7 Merge pull request #5400 from BookStackApp/laravel11
Laravel 11 Upgrade
2025-01-13 13:27:32 +00:00
Dan Brown
ee88832f1a Updated translations with latest Crowdin changes (#5399) 2025-01-13 13:26:04 +00:00
Dan Brown
dbda82ef92 Framework: Re-add updated patched symfony-mailer
https://github.com/ssddanbrown/symfony-mailer/commit/e9de8dccd76a63fc23475016e6574da6f5f12a2
2025-01-11 15:05:10 +00:00
Dan Brown
ad8bc5fe21 Framework: Updated phpunit to 11, updated migration test php versions 2025-01-11 13:50:01 +00:00
Dan Brown
5bf75786c6 Framework: Fixed Laravel 11 upgrade test issues, updated phpstan
- Fixed failing tests due to Laravel 11 changes
- Updated phpstan to 3.x branch
- Removed some seemingly redundant comment code, which was triggering
  phpstan.
2025-01-11 13:22:49 +00:00
Dan Brown
cf9ccfcd5b Framework: Performed Laravel 11 upgrade guide steps
Performed a little code cleanups when observed along the way.
Tested not yet ran.
2025-01-11 11:14:49 +00:00
Dan Brown
5116d83d38 PHP: Updated min version to 8.2
PHPStan config not yet compatible, but should work after moving to Laravel
11, which would allow using larastan 3.x.
2025-01-09 16:46:13 +00:00
Dan Brown
387c786768 Updated version and assets for release v24.12.1 2025-01-04 22:22:17 +00:00
Dan Brown
2641586a6f Merge branch 'development' into release 2025-01-04 22:22:04 +00:00
Dan Brown
33b46882f3 Updated translations with latest Crowdin changes (#5370) 2025-01-04 21:46:35 +00:00
Dan Brown
9a5c287470 Deps: Updated composer packages 2025-01-04 21:45:36 +00:00
Dan Brown
6effc6d262 Merge pull request #5379 from BookStackApp/better_cleanup
Export limits and cleanup
2025-01-04 21:05:45 +00:00
Dan Brown
ff6c5aaecb Markdown Editor: Fixed scroll jump on image upload
For #5384
2025-01-04 21:01:28 +00:00
Dan Brown
1ff2826678 Exports: Added rate limits for UI exports
Just as a measure to prevent potential abuse of these potentially
longer-running endpoints.
Adds test to cover for ZIP exports, but applied to all formats.
2025-01-01 15:42:59 +00:00
Dan Brown
7e31725d48 Exports: Improved PDF command temp file cleanup 2025-01-01 15:19:11 +00:00
Dan Brown
6d7ff59a89 ZIP Exports: Improved temp file tracking & clean-up 2024-12-31 15:13:50 +00:00
Dan Brown
6d2cd20e80 Updated version and assets for release v24.12 2024-12-23 11:55:23 +00:00
Dan Brown
b0c574356a Merge branch 'development' into release 2024-12-23 11:55:02 +00:00
Dan Brown
980a684b14 Updated translator & dependency attribution before release v24.12 2024-12-23 11:53:35 +00:00
Dan Brown
d56eea9279 Locales: Updated locale list with new languages 2024-12-23 11:27:58 +00:00
Dan Brown
2be504e0d2 Updated translations with latest Crowdin changes (#5345) 2024-12-23 11:23:44 +00:00
Dan Brown
c84d999456 ZIP Exports: Prevent book child page drafts from being included
Added test to cover
2024-12-22 12:43:26 +00:00
Dan Brown
01825ddb93 Dependancies: Bumped up composer dep versions 2024-12-21 15:48:46 +00:00
Dan Brown
1f88bc2a59 Merge pull request #5365 from BookStackApp/lexical_fixes
Range of fixes/updates for the new Lexical based editor
2024-12-20 14:51:57 +00:00
Dan Brown
ebe2ca7faf Lexical: Added about button/view
Re-used existing route and moved tinymce help to its own different
route. Added test to cover.
Added new external-content block to support in editor UI.
2024-12-17 22:40:28 +00:00
Dan Brown
f4005a139b Lexical: Adjusted handling of child/sibling list items on nesting
Sibling/child items will now remain at the same visual level during
nesting/un-nested, so only the selected item level is visually altered.

Also added new model-based editor content matching system for tests.
2024-12-17 18:07:46 +00:00
Dan Brown
fca8f928a3 Lexical: Aligned new empty item behaviour for nested lists
- Makes enter on empty nested list item un-nest instead of just creating
  new list items.
- Also updated existing lists tests to use newer helper setup.
2024-12-17 16:52:14 +00:00
Dan Brown
ace8af077d Lexical: Improved list tab handling, Improved test utils
- Made tab work on empty list items
- Improved select preservation on single list item tab
- Altered test context creation for more standard testing
2024-12-17 14:44:10 +00:00
Dan Brown
e50cd33277 Lexical: Added testing for some added shortcuts
Also:
- Added svg loading support (dummy stub) for jest.
- Updated headless test case due to node changes.
- Split out editor change detected to where appropriate.
- Added functions to help with testing, like mocking our context.
2024-12-16 16:27:44 +00:00
Dan Brown
8486775edf Lexical: Added mulitple methods to escape details block
Enter on empty last line, or down on last empty line, will focus on the
next node after details, or created a new paragraph to focus on if
needed.
2024-12-16 14:30:06 +00:00
Dan Brown
5887322178 Lexical: Added details toolbar
Includes unwrap and toggle open actions.
2024-12-15 18:13:49 +00:00
Dan Brown
3f86937f74 Lexical: Made summary part of details node
To provide more control of the summary as part of details.
To support, added a way to ignore elements during import DOM, allowing
up to read summaries when parsing details without duplicate nodes
involved.
2024-12-15 17:12:54 +00:00
Dan Brown
2f119d3033 Lexical: Adjusted modals and content area for mobile sizes 2024-12-15 15:29:00 +00:00
Dan Brown
5f07f31c9f Lexical: Added mobile toolbar support
Adds dynamic and fixed (out of DOM order) positioning with location
adjustment depending on space.
Also adds smarter hiding to prevent disappearing when mouse leaves but
within the same space as the toggle.
2024-12-15 14:03:08 +00:00
Dan Brown
a71aa241ad Lexical: Added dark mode styles, fixed autolink range 2024-12-14 15:17:33 +00:00
Dan Brown
97b201f61f Lexical: Added auto links on enter/space 2024-12-14 12:35:13 +00:00
Dan Brown
a8ef820443 Users: Hid lanuage preference for guest user
Hiding since it's not really used, and may mislead on how to set default
app language (which should be done via env options).
Updated test to cover.

For #5356
2024-12-13 15:19:28 +00:00
Dan Brown
7e1a8e5ec6 API: Added cover to book/shelf list endpoints
Aligns with what we provide in the UI.
Added/updated tests to cover, and updated API examples.

For 5180.
2024-12-13 14:21:04 +00:00
Dan Brown
19ee1c9be7 Notifications: Logged errors and prevented them blocking user
Failed notification sends could block the user action, whereas it's
probably more important that the user action takes places uninteruupted
than showing an error screen for the user to debug.
Logs notification errors so issues can still be debugged by admins.

Closes #5315
2024-12-12 21:47:39 +00:00
Dan Brown
fcf0bf79a9 Attachments: Hid edit/delete controls where lacking permission
Added test to cover.
Also migrated related ajax-delete-row component to ts.

For #5323
2024-12-11 20:38:30 +00:00
Dan Brown
0ece664475 CI: Added php8.4 to CI suites, bumped action/os versions 2024-12-11 18:50:10 +00:00
Dan Brown
509af2463d Search Index: Fixed SQL error when indexing large pages
Due to hitting statement placeholder limits (typically 65k)
when inserting index terms for single page.

Added test to cover.
Also added skipped tests for tests we don't always want to run.
For #5322
2024-12-11 15:55:19 +00:00
Dan Brown
5632fef621 Auth: Added specific guards against guest account login
Hardened things to enforce the intent that the guest account should not
be used for logins.
Currently this would not be allowed due to empty set password, and no
password fields on user edit forms, but an error could occur if the
login was attempted.

This adds:
- Handling to show normal invalid user warning on login instead of a
  hash check error.
- Prevention of guest user via main login route, in the event that
  inventive workarounds would be used by admins to set a password for
  this account.
- Test for guest user login.
2024-12-11 14:22:48 +00:00
Dan Brown
8ec26e8083 SASS: Updated to use modules and address deprecations
Changes the name of our spacing variables due to the prefixing -/_
meaning private in the use of new "use" rather than include.

All now modular too, so all variables/mixins are accessed via their
package.

Also renamed variables file to vars for simpler/cleaner access/writing.

eg. '$-m' is now 'vars.$m'
2024-12-09 13:25:35 +00:00
Dan Brown
617b2edea0 JS: Updated packages, fixed lint issue
Left eslint as old due to eslint-config-airbnb-base not yet being
comptible.
Some SASS deprecations to solve.
2024-12-09 13:07:39 +00:00
Dan Brown
55d074f1a5 Attachment API: Fixed error when name not provided in update
Fixes #5353
2024-12-09 11:32:15 +00:00
Dan Brown
7e6f6af463 Merge pull request #5349 from BookStackApp/lexical_reorg
Lexical: Merge of custom nodes & re-organisation of codebase
2024-12-04 20:06:39 +00:00
Dan Brown
d00cf6e1ba Lexical: Updated tests for node changes 2024-12-04 20:03:05 +00:00
Dan Brown
9fdd100f2d Lexical: Reorganised custom node code into lexical codebase
Also cleaned up old unused imports.
2024-12-04 18:53:59 +00:00
Dan Brown
57d8449660 Lexical: Merged custom table node code 2024-12-03 20:08:33 +00:00
Dan Brown
ebd4604f21 Lexical: Merged list nodes 2024-12-03 19:03:52 +00:00
Dan Brown
36a4d79120 Lexical: Extracted & merged heading & quote nodes 2024-12-03 17:04:50 +00:00
Dan Brown
f3fa63a5ae Lexical: Merged custom paragraph node, removed old format/indent refs
Start of work to merge custom nodes into lexical, removing old unused
format/indent core logic while extending common block elements where
possible.
2024-12-03 16:24:49 +00:00
Dan Brown
5164375b18 Merge branch 'rashadkhan359/development' into development 2024-12-03 13:52:38 +00:00
Dan Brown
fec44452cb Search API: Updated handling of parent detail, added testing
Review of #5280.

- Removed additional non-needed loads which could ignore permissions.
- Updated new formatter method name to be more specific on use.
- Added test case to cover changes.
- Updated API examples to align parent id/info in info to be
  representative.
2024-12-03 13:51:46 +00:00
Dan Brown
18ab38a87b Merge branch 'fix/markdown-export' into development 2024-12-02 11:50:15 +00:00
Dan Brown
0f9957bc03 MD Exports: Added HTML description conversion
Also updated tests to cover checking description use/conversion.
Made during review of #5313
2024-12-02 11:46:56 +00:00
Dan Brown
80f258c3c5 Merge branch 'fix-ldap-display-name' into development 2024-12-01 18:44:23 +00:00
Dan Brown
90341e0e00 LDAP: Review and testing of mulitple-display-name attr support
Review of #5295
Added test to cover functionality.
Moved splitting from config to service.
2024-12-01 18:42:54 +00:00
Dan Brown
3298374113 Merge branch 'docker-simplify' into development 2024-12-01 16:10:22 +00:00
Dan Brown
227c5e155b Dev Docker: Fixed missing gd jpeg handling, forced migrations
Migrations run without force could fail startup in certain environment
conditions (when testing production env).
Also updated paths permission handling to update more needed locations.
2024-12-01 16:10:05 +00:00
Dan Brown
fdbbcf2b8a Merge branch 'portazips' into development 2024-12-01 13:06:43 +00:00
Dan Brown
0a07b0d162 Merge pull request #5259 from BookStackApp/typescript-conversions
Conversion of Services to TypeScript
2024-12-01 13:04:59 +00:00
Dan Brown
07e45a20e5 Updated version and assets for release v24.10.3 2024-11-29 13:50:41 +00:00
Dan Brown
14056c69e6 Updated version and assets for release v24.10.2 2024-11-29 13:47:24 +00:00
Dan Brown
fb9c840c46 Merge branch 'development' into release 2024-11-29 13:47:08 +00:00
Dan Brown
94165cc18f Updated translator & dependency attribution before release v24.10.2 2024-11-29 13:46:37 +00:00
Dan Brown
f5ecd51461 Updated translations with latest Crowdin changes (#5331) 2024-11-29 13:40:09 +00:00
Dan Brown
e9f906ce56 Attachments: Fixed full range request handling
We were not responsing with a range request, where the requested range
was for the full extent of content. This changes things to always
provide a range request, even for the full range.

Change made since our existing logic could cause problems in chromium
browsers.

Elseif statement removed as its was likley redundant based upon other
existing checks.
This also changes responses for requested ranges beyond content, but I
think that's technically correct looking at the spec (416 are for when
there are no overlapping request/response ranges at all).

Updated tests to cover.
For #5342
2024-11-29 13:19:55 +00:00
Dan Brown
4630f07282 Code: Set base codemirror line height
Prevents difference in line height between light/dark mode.
For #5146
2024-11-29 12:57:53 +00:00
Dan Brown
978acecdcf Merge branch 'oidc-content-type-issue' into development 2024-11-28 16:58:55 +00:00
Dan Brown
bc1f1d92e5 OIDC: Added extra userinfo content-type normalisation and test
During review of #5337
2024-11-28 16:58:06 +00:00
Dan Brown
415cd6a360 Includes: Workaround for PHP 8.3.14 bug
Changed DOMText creation to be done via document so its document
reference is correct to avoid a bug in PHP 8.3.14.
Ref: https://github.com/php/php-src/issues/16967

Fixes #5341
2024-11-28 16:30:59 +00:00
Dan Brown
68ce340741 Depenencies: Updated PHP packages 2024-11-28 16:25:01 +00:00
Dan Brown
bdca9fc1ce ZIP Exports: Changed the instance id mechanism
Adds an instance id via app settings.
2024-11-27 16:30:19 +00:00
Dan Brown
edb684c72c ZIP Exports: Updated format doc with advisories regarding html/md 2024-11-26 17:53:20 +00:00
Wes Biggs
17f7afe12d Updates the OIDC userinfo endpoint request to allow for a Content-Type response header with optional parameters, like application/json; charset=utf-8. This was causing an issue when integrating with [node-oidc-provider](https://github.com/panva/node-oidc-provider). 2024-11-26 11:21:20 -06:00
Dan Brown
0a182a45ba ZIP Exports: Added detection/handling of images with external storage
Added test to cover.
2024-11-26 15:59:39 +00:00
Dan Brown
95d62e7f57 ZIP Imports/Exports: Fixed some lint and test issues
- Updated test handling to create imports folder when required.
- Updated some tests to delete created import zip files.
2024-11-25 16:30:56 +00:00
Dan Brown
9ecc91929a ZIP Import & Exports: Addressed issues during testing
- Handled links to within-zip page images found in chapter/book
  descriptions; Added test to cover.
- Fixed session showing unrelated success on failed import.

Tested import file-create undo on failure as part of this testing.
2024-11-25 15:54:15 +00:00
Dan Brown
f79c6aef8d ZIP Imports: Updated import form to show loading indicator
And disable button after submit.
Added here because the import could take some time, so it's best to show
an indicator to the user to show that something is happening, and help
prevent duplicate submission or re-submit attempts.
2024-11-22 21:36:42 +00:00
Dan Brown
c0dff6d4a6 ZIP Imports: Added book content ordering to import preview 2024-11-22 21:03:04 +00:00
Dan Brown
59cfc087e1 ZIP Imports: Added image type validation/handling
Images were missing their extension after import since it was
(potentially) not part of the import data.
This adds validation via mime sniffing (to match normal image upload
checks) and also uses the same logic to sniff out a correct extension.

Added tests to cover.
Also fixed some existing tests around zip functionality.
2024-11-18 17:42:49 +00:00
Dan Brown
e2f6e50df4 ZIP Exports: Added ID checks and testing to validator 2024-11-18 15:53:21 +00:00
Dan Brown
c2c64e207f ZIP Imports: Covered import runner with further testing 2024-11-16 19:52:20 +00:00
Dan Brown
8645aeaa4a ZIP Imports: Started testing core import logic
Fixed image size handling, and lack of attachment reference replacements
during testing.
2024-11-16 16:12:45 +00:00
Dan Brown
7681e32dca ZIP Imports: Added high level import run tests 2024-11-16 13:57:41 +00:00
Dan Brown
b7476a9e7f ZIP Import: Finished base import process & error handling
Added file creation reverting and DB rollback on error.
Added error display on failed import.
Extracted likely shown import form/error text to translation files.
2024-11-14 15:59:15 +00:00
Dan Brown
5fba4a5399 Updated version and assets for release v24.10.2 2024-11-13 12:03:15 +00:00
Dan Brown
c0b377050e Merge branch 'development' into release 2024-11-13 12:02:30 +00:00
Dan Brown
306b8774c2 Updated translations with latest Crowdin changes (#5317)
* New translations common.php (Ukrainian)

* New translations entities.php (Ukrainian)

* New translations errors.php (Ukrainian)

* New translations activities.php (Czech)

* New translations entities.php (Czech)
2024-11-13 11:59:03 +00:00
Dan Brown
c40ab4147e Dependencies: Updated composer packages 2024-11-13 11:39:04 +00:00
Dan Brown
48c101aa7a ZIP Imports: Finished off core import logic 2024-11-11 15:06:46 +00:00
Dan Brown
378f0d595f ZIP Imports: Built out reference parsing/updating logic 2024-11-10 16:03:50 +00:00
czemu
f12946d581 ExportFormatter: Add book description and check for empty book and chapter descriptions in markdown export 2024-11-10 09:39:33 +01:00
Dan Brown
d13e4d2eef ZIP imports: Started actual import logic 2024-11-09 14:01:24 +00:00
Dan Brown
f3efb6441d Updated version and assets for release v24.10.1 2024-11-08 13:53:06 +00:00
Dan Brown
0cf313a21e Merge branch 'development' into release 2024-11-08 13:52:37 +00:00
Dan Brown
ac27e18933 Languages: Added Turkmen to locale manager 2024-11-08 13:46:57 +00:00
Dan Brown
e5a6ccc4d4 Translators: Updated before patch release 2024-11-08 13:31:21 +00:00
Dan Brown
e42cdbe8e0 Updated translations with latest Crowdin changes (#5250) 2024-11-08 13:29:21 +00:00
Dan Brown
a6ba8dd68f Testing: Improved reliability
- Added extra column/value check for page revision test for accuracy.
- Changed search sort test to use more reliable values.
  - Change due to database seeding somtimes generating values that
    proceeded the test value, expected to be first, in sort results.
2024-11-08 11:35:18 +00:00
Dan Brown
7017a1cae5 Update URL Command: Added revisions table support
For #5292
Added test to cover.
2024-11-08 11:22:30 +00:00
Dan Brown
8120278b8c PHP Deps: Bumped up minor versions 2024-11-08 10:41:25 +00:00
Dan Brown
73babcbfe3 Merge pull request #5312 from BookStackApp/system_cli_update
System CLI update
2024-11-07 17:22:08 +00:00
Dan Brown
45189d9517 System CLI: Updated to 126de5599c state 2024-11-07 17:10:35 +00:00
Dan Brown
7b84558ca1 ZIP Imports: Added parent and permission check pre-import 2024-11-05 15:41:58 +00:00
Dan Brown
92cfde495e ZIP Imports: Added full contents view to import display
Reduced import data will now be stored on the import itself, instead of
storing a set of totals.
2024-11-05 13:17:31 +00:00
Dan Brown
14578c2257 ZIP Imports: Added parent selector for page/chapter imports 2024-11-04 16:21:22 +00:00
Dan Brown
8f6f81948e ZIP Imports: Fleshed out continue page, Added testing 2024-11-03 17:28:18 +00:00
Dan Brown
c6109c7087 ZIP Imports: Added listing, show view, delete, activity 2024-11-03 14:13:05 +00:00
Dan Brown
8ea3855e02 ZIP Import: Added upload handling
Split attachment service storage work out so it can be shared.
2024-11-02 20:48:21 +00:00
Dan Brown
74fce9640e ZIP Import: Added model+migration, and reader class 2024-11-02 17:17:34 +00:00
Dan Brown
259aa829d4 ZIP Imports: Added validation message display, added testing
Testing covers main UI access, and main non-successfull import actions.
Started planning stored import model.
Extracted some text to language files.
2024-11-02 14:51:04 +00:00
Dan Brown
c4ec50d437 ZIP Exports: Got zip format validation functionally complete 2024-10-30 15:26:23 +00:00
Dan Brown
b50b7b667d ZIP Exports: Started import validation 2024-10-30 13:13:41 +00:00
Zero
fbeb2e23d4 fix deprecated syntax 2024-10-29 23:07:15 +08:00
Zero
4b60c03caa re-write Dockerfile 2024-10-29 23:06:50 +08:00
Dan Brown
a56a28fbb7 ZIP Exports: Built out initial import view
Added syles for non-custom, non-image file inputs.
Started planning out back-end handling.
2024-10-29 14:21:32 +00:00
Dan Brown
4051d5b803 ZIP Exports: Added new import permission
Also updated new route/view to new non-book-specific flow.
Also fixed down migration of old export permissions migration.
2024-10-29 12:11:51 +00:00
Matthieu Leboeuf
87242ce6cb Adapt tests with displayName array 2024-10-28 22:27:15 +01:00
Matthieu Leboeuf
72d9ffd8b4 Added support for concatenating multiple LDAP attributes in displayName 2024-10-28 22:14:30 +01:00
Rashad
f606711463 respective book and chapter structure added. 2024-10-27 22:50:20 +05:30
Dan Brown
d1f69feb4a ZIP Exports: Tested each type and model of export 2024-10-27 14:33:43 +00:00
Dan Brown
e4ca3bf132 Merge pull request #5291 from LordSimal/development
fix tests namespace definition
2024-10-27 09:54:11 +00:00
Kevin Pfeifer
7aaf866064 fix tests namespace definition 2024-10-26 13:24:49 +02:00
Dan Brown
484342f26a ZIP Exports: Added entity cross refs, Started export tests 2024-10-23 15:59:58 +01:00
Dan Brown
42ada66fdd ZIP Exports: Added core logic for books/chapters 2024-10-23 11:30:32 +01:00
Dan Brown
f732ef05d5 ZIP Exports: Reorganised files, added page md parsing 2024-10-23 10:48:26 +01:00
Dan Brown
4fb4fe0931 ZIP Exports: Added working image handling/inclusion 2024-10-21 13:59:15 +01:00
Dan Brown
06ffd8ee72 Zip Exports: Added attachment/image link resolving & JSON null handling 2024-10-21 12:13:41 +01:00
Rashad
90a8070518 Eager loading for titles 2024-10-21 03:01:33 +05:30
Rashad
3e656efb00 Added include func for search api 2024-10-21 02:42:49 +05:30
Dan Brown
7c39dd5cba ZIP Export: Started building link/ref handling 2024-10-20 19:56:56 +01:00
Dan Brown
21ccfa97dd ZIP Export: Expanded page & added base attachment handling 2024-10-19 15:41:07 +01:00
Dan Brown
bf0262d7d1 Testing: Split export tests into multiple files 2024-10-19 13:59:42 +01:00
Dan Brown
42b9700673 ZIP Exports: Finished up format doc, move files, started builder
Moved all existing export related app files into their new own dir.
2024-10-15 16:14:11 +01:00
Dan Brown
42bd07d733 ZIP Export: Continued expanding format doc types 2024-10-15 13:57:16 +01:00
Dan Brown
6f1c54d018 Users: Changed name validation to min:1 instead of 2
Would cause scenarios where users could be created with 1 char, but then
fail to update due to validation differences.
Added test to cover.
For #5263
2024-10-15 11:07:41 +01:00
Dan Brown
1930af91ce ZIP Export: Started types in format doc 2024-10-13 22:56:22 +01:00
Dan Brown
e088d09e47 ZIP Export: Started defining format 2024-10-13 14:18:23 +01:00
Dan Brown
209fa04752 TS: Converted dom and keyboard nav services 2024-10-11 21:55:51 +01:00
Dan Brown
f41c02cbd7 TS: Converted app file and animations service
Extracted functions out of app file during changes to clean up.
Altered animation function to use normal css prop names instead of JS
CSS prop names.
2024-10-11 15:19:19 +01:00
Dan Brown
4dc75bad05 Settings: Added test to cover setting category by view 2024-10-11 13:33:07 +01:00
Lachlan Tripolone
a3d0f7478f Move settings category layouts into their own view folder 2024-10-11 10:42:48 +11:00
Lachlan Tripolone
b9b5003239 Refactor SettingController to validate categies by existing view files 2024-10-11 10:40:38 +11:00
Dan Brown
2e8d6ce7d9 TS: Coverted util service 2024-10-10 12:03:24 +01:00
Dan Brown
26aadffb20 Updated version and assets for release v24.10 2024-10-09 10:48:34 +01:00
Dan Brown
a5f48e3202 Merge branch 'development' into release 2024-10-09 10:46:07 +01:00
Dan Brown
a58102d6ef Attribution: Updated translator & license files before v24.10 2024-10-09 10:26:07 +01:00
Dan Brown
65453bd94e Updated translations with latest Crowdin changes (#5188) 2024-10-09 10:21:55 +01:00
Dan Brown
d22413b931 JS: Converted/updated translation code to TS, fixed some comment counts
- Migrated translation service to TS, stripping a lot of now unused code
  along the way.
- Added test to cover translation service.
- Fixed some comment count issues, where it was not showing correct
  value. or updating, on comment create or delete.
2024-10-07 22:55:10 +01:00
Dan Brown
8b9bcc1768 Search: Fixed last commented filter when using table prefixes 2024-10-05 15:20:04 +01:00
Dan Brown
51287d545b Searching: Fixed some form search issues
- Form was not retaining certain filters
- Form request handling of entity type set wrong filter name
Added test to cover.
2024-10-05 14:49:30 +01:00
Dan Brown
c314a60a16 WYSIWYG: Code & table fixes
- Fixed new code block insertion to remove selection area instead of
  just adding after.
- Added default table column widths to not be collapsed
- Updated table dom export to not duplicate colgroups.
2024-10-05 12:42:47 +01:00
Dan Brown
9b2520aa0c WYSIWYG: Fixed list indenting selection & display bugs
- Fixed selection breaking on multiple indent changes
- Fixed multi-indent showing numbers on empty child list until the nodes
  are fully re-rendered.
2024-10-04 15:11:09 +01:00
Dan Brown
346b88ae43 JS: Converted a few extra services to TS 2024-10-04 14:36:20 +01:00
Dan Brown
2766c76491 TinyMCE: Updated version from 6.8.3 to 6.8.4 2024-10-04 12:46:22 +01:00
Dan Brown
be6529d0a1 New WYSIWYG: Added mac shortcut support 2024-10-04 12:41:13 +01:00
Dan Brown
b1a3ea1aa4 Languages: Enabled Welsh option 2024-10-04 11:02:17 +01:00
Dan Brown
6646dcc24d Merge pull request #5239 from BookStackApp/search_negation
Search term negation
2024-10-03 19:52:06 +01:00
Dan Brown
966ff91386 Search: Prevented negated terms filling in UI inputs
Added test to cover.
2024-10-03 19:40:11 +01:00
Dan Brown
cd84d08157 Search: Added exact/filter/tag term negation support 2024-10-03 19:27:03 +01:00
Dan Brown
93c677a6a9 Searching: Added negation support to UI and term handling
Updated/added tests to cover.
Support for actual search queries still remains.
2024-10-03 15:59:50 +01:00
Dan Brown
177cfd72bf Search: Added structure for search term inputs
Sets things up to allow more complex terms ready to handle negation.
2024-10-02 17:31:45 +01:00
Dan Brown
34ade50181 Base layout: Changed main app script to be module loaded
Prevents polluting global scope with variables since we're using the
module format bundler in esbuild.
Also cleaned up unused yields.
Fixed bad reference in our tinymce fixes.

For #5232
2024-10-01 10:37:31 +01:00
Dan Brown
e65655594f Merge branch 'feature/opensearch' into development 2024-09-30 17:21:51 +01:00
Dan Brown
514db60617 Tests: Categorised up meta tests
Extracted robots.txt tests into its own file to fit into new folder.
Also tweaked open search tests a tad to specifically check long app
names.
2024-09-30 17:07:53 +01:00
Dan Brown
8bc6e75319 Code Blocks: Added SAS and R language options
For #5206
2024-09-30 16:47:55 +01:00
Maximilian Walter
2f74cfb42c Add test for OpenSearch endpoint 2024-09-30 17:45:20 +02:00
Maximilian Walter
1302e3c959 Add missing XML declaration to OpenSearch endpoint 2024-09-30 17:45:20 +02:00
Maximilian Walter
a5b031f906 Translatable description for OpenSearch XML 2024-09-30 17:45:20 +02:00
Dan Brown
f583354748 Maintenance: Removed stray dd from last commit 2024-09-29 16:50:48 +01:00
Dan Brown
d12e8ec923 Users: Improved user response for failed invite sending
Added specific handling to show relevant error message when user
creation fails due to invite sending errors, while also returning user
to the form with previous input.
Includes test to cover.

For #5195
2024-09-29 16:41:18 +01:00
Dan Brown
89f84c9a95 Pages: Updated editor field to always be set
- Migration for setting on existing pages
- Added test to cover simple new page scenario

For #5117
2024-09-29 14:36:41 +01:00
Dan Brown
6103a22feb Exports: Made pdf command timeout configurable
Added test to cover.
For #5119
2024-09-27 16:33:58 +01:00
Dan Brown
42264f402d CSS: Fixed floating search icon on mobile
Also updated styles to use logical elements instead of conditional rules
for altered search boxes.
Related to #2504
2024-09-27 16:02:13 +01:00
Dan Brown
abda9bc00a PHP Dependancies: Updated packages pending major version changes
Closes #5222
2024-09-27 14:21:12 +01:00
Dan Brown
eec639d84e Maintenance: Fixed js lint and SCSS build warnings 2024-09-27 13:57:39 +01:00
Dan Brown
56b9107c6b Dependancies: Updated php & JS deps, updated license lists
Fixed issue now picked up by newer TS version
2024-09-27 12:29:19 +01:00
Dan Brown
b35b62d59f Merge branch 'lexical' into development 2024-09-27 12:04:01 +01:00
Dan Brown
1b9310e766 Meta: Added lexical licensing info and added TS/JS CI testing 2024-09-27 10:45:48 +01:00
Dan Brown
a62d8381be Lexical: Updated toolbar & text node exporting
- Updated toolbar to match existing editor, including dynamic RTL/LTR
  controls.
- Updated text node handling to not include spans and extra classes when
  not needed. Added & update tests to cover.
2024-09-23 17:36:16 +01:00
Dan Brown
8b32e6c15a Page Editors: Added switching/options for new lexical editor 2024-09-22 20:06:55 +01:00
Dan Brown
c8ccb2bac7 Lexical: Range of fixes
- Prevented ui shortcuts running in editor
- Added form modal closing on submit
- Fixed ability to escape lists via enter on empty last item
2024-09-22 16:15:02 +01:00
Dan Brown
ef3de1050f Lexical: Added UI translation support 2024-09-22 12:29:06 +01:00
Dan Brown
2add15bd72 Lexical: Added direction support to extra blocks
Also removed duplicated dir functionality that remained in core.
2024-09-22 12:07:24 +01:00
Dan Brown
e6edd9340e Lexical: Added alignment detoggle, fixed inital focus area 2024-09-21 17:02:54 +01:00
Dan Brown
654a7a5d03 Lexical: Removed reconciler level direction handling
- Updated tests to consider changes
2024-09-21 13:00:16 +01:00
Dan Brown
dba8ab947f Lexical: Finished conversion/update of test files 2024-09-20 15:31:19 +01:00
Dan Brown
787e06e3d8 Lexical: Adapted a range of further existing tests 2024-09-20 13:05:29 +01:00
Dan Brown
ccd486f2a9 Lexical: Got a range of Editor tests working 2024-09-18 17:31:51 +01:00
Dan Brown
22d078b47f Lexical: Imported core lexical libs
Imported at 0.17.1, Modified to work in-app.
Added & configured test dependancies.
Tests need to be altered to avoid using non-included deps including
react dependancies.
2024-09-18 13:43:39 +01:00
Dan Brown
03490d6597 Lexical: Added RTL/LTR actions
Kinda useless though due to Lexical reconciler :(
2024-09-16 12:29:46 +01:00
Dan Brown
5f46d71af0 Lexical: Fixed a range of issues in RTL mode 2024-09-15 16:10:46 +01:00
Maximilian Walter
4f890c431c Limit short-name for OpenSearch XML to 16 characters
The specification does not allow more than 16 characters.
2024-09-14 15:31:56 +02:00
Maximilian Walter
c110a97d8a Remove unofficial method-attribute from OpenSearch-XML 2024-09-14 15:24:42 +02:00
Dan Brown
6872eb802c Lexical: Altered keyboard handling to indicant handled state 2024-09-13 16:05:55 +01:00
Dan Brown
662110c269 Lexical: Custom list nesting support
Added list nesting support to allow li > ul style nesting which lexical
didn't do by default.
Adds tab handling for inset/outset controls.
Will be a range of edge-case bugs to squash during testing.
2024-09-13 15:50:42 +01:00
Dan Brown
5083188ed8 Lexical: Added block indenting capability
Needed a custom implementation due to hardcoded defaults for Lexical
default indenting.
2024-09-10 15:55:46 +01:00
Dan Brown
2036438203 Lexical: Added single node enter handling
Also updated media to be an inline element to align with old editor
behaviour.
2024-09-10 12:14:26 +01:00
Maximilian Walter
476c2be5a6 Add XML for OpenSearch 2024-09-09 22:54:33 +02:00
Dan Brown
ced66f1671 Lexical: Added single node backspace/delete support 2024-09-09 18:33:54 +01:00
Dan Brown
fb49371c6b Lexical: Refined editor UI
- Cleaned up dropdown lists to look integrated
- Added icons for color picker clear and menu list items
2024-09-09 14:06:41 +01:00
Dan Brown
fd07aa0f05 Lexical: Further fixes
- Improved node resizer positioning to be more accurate
- Fixed drop handling not running within editor margin space
- Made media dom update smarter to reduce reloads
- Fixed media alignment, broken due to added wrapper
2024-09-09 12:28:01 +01:00
Dan Brown
16518a4f89 Lexical: Range of bug fixes, Updated lexical version
- Updated selection change detection to be more accurate
- Added UI refresh for extra actions
- Fixed remove link deleting contents
2024-09-08 15:54:59 +01:00
Dan Brown
bed2c29a33 Lexical: Added media resize support via drag handles 2024-09-08 13:37:13 +01:00
Dan Brown
e5b6d28bca Lexical: Revamped image node resize method
Changed from using a decorator to using a helper that watches for image
selections to then display a resize helper.
Also changes resizer to use a ghost and apply changes on end instead of
continuosly during resize.
2024-09-07 18:39:58 +01:00
Dan Brown
1c9afcb84e Lexical: Added some level of img/media alignment 2024-09-06 14:07:10 +01:00
Dan Brown
b0dda6e6a7 Updated version and assets for release v24.05.4 2024-08-29 16:04:51 +01:00
Dan Brown
d4025d95e7 Merge branch 'development' into release 2024-08-29 16:04:37 +01:00
Dan Brown
3a058a6e34 Merge branch 'development' of github.com:BookStackApp/BookStack into development 2024-08-29 15:28:52 +01:00
Dan Brown
aac7d564c8 Updated translations with latest Crowdin changes (#5118) 2024-08-29 15:08:27 +01:00
Dan Brown
9aa3442a17 API: Fixed lacking permission enforcement on book contents 2024-08-29 14:43:21 +01:00
Dan Brown
c68d154f0f LDAP: Updated tests for recursive group changes 2024-08-28 21:16:18 +01:00
Dan Brown
1b4ed69f41 LDAP: Updated recursive group search to query by DN
Added test to cover, added pre-change.
Need to test post-changes and fix tests.
2024-08-28 15:39:05 +01:00
Dan Brown
8cef998f49 RTL: Fixed lacking task list RTL support
Added with fallback to old LTR styles.
For #5134
2024-08-27 14:13:33 +01:00
Dan Brown
90d1223acd Styles: Added max-width for iframes in content
For #5130
2024-08-27 13:32:16 +01:00
Dan Brown
1f2506221a API: Updated docs with consistent types, fixed users response example
For #5178 and #5183
2024-08-27 12:23:36 +01:00
Dan Brown
9f68ca5358 Dependancies: Updated PHP and JS packages 2024-08-26 11:49:02 +01:00
Dan Brown
1ebb0f8c93 Lexical: Added table column cut/copy/paste support 2024-08-22 13:28:30 +01:00
Dan Brown
8a13a9df80 Lexical: Improved table row copy/paste
Added safeguarding/matching of source/target sizes to prevent broken
tables.
2024-08-22 10:08:08 +01:00
Dan Brown
ddf5f2543c Lexical: Added drop/paste image handling 2024-08-21 12:59:45 +01:00
Dan Brown
dbb2fe3e59 Lexical: Finished off baseline shortcut implementation 2024-08-20 14:54:53 +01:00
Dan Brown
aa1fac62d5 Lexical: Started adding editor shortcuts 2024-08-20 13:07:33 +01:00
Dan Brown
111a313d51 Lexical: Added custom alignment handling for blocks
To align with pre-existing use of alignment classes.
2024-08-18 16:51:08 +01:00
Dan Brown
0039f893cc Lexical: Integrated diagram manager, added menu split button 2024-08-17 10:48:34 +01:00
Dan Brown
ad6b26ba97 Lexical: Added basic URL field header option list
May show bad option label names on chrome/safari.
This was an easy first pass without loads of extra custom UI since we're
using native datalists.
2024-08-16 12:29:40 +01:00
Dan Brown
1ef4044419 Lexical: Connected link selector to link form 2024-08-16 11:22:12 +01:00
Dan Brown
accf2565a0 Lexical: Integrated image manager to image button/form 2024-08-13 19:36:18 +01:00
Dan Brown
ec965f28c0 Lexical: Added id support for all main block types 2024-08-11 16:08:51 +01:00
Dan Brown
ebf95f637a Lexical: Wired table properties, and other buttons 2024-08-10 13:14:55 +01:00
Dan Brown
abbfd42a6c Lexical: Kinda made row copy/paste work 2024-08-09 21:58:45 +01:00
Dan Brown
db4208a7eb Lexical: Linked row properties form up 2024-08-09 12:42:04 +01:00
Dan Brown
da54e1d87c Lexical: Added cell width fetching, Created custom row node 2024-08-09 11:24:25 +01:00
Dan Brown
e8532ef4de Lexical: Added merge cell logic 2024-08-07 20:32:54 +01:00
Dan Brown
fa6d66db49 Readme: Updated sponsor image links to use website 2024-08-07 10:53:20 +01:00
Alexander Wilms
6604e7365f Update sponsor image URLs in readme 2024-08-06 23:30:05 +00:00
Dan Brown
fcc1c2968d Lexical: Added table cell node import logic 2024-08-06 09:36:37 +01:00
Dan Brown
b3d3b14f79 Lexical: Finished off core cell properties functionality 2024-08-05 18:49:17 +01:00
Dan Brown
8939f310db Lexical: Started linking up cell properties form 2024-08-05 15:08:52 +01:00
Dan Brown
efec752985 Lexical: Split helpers to utils, refactored files 2024-08-03 18:14:01 +01:00
Dan Brown
e94ad78ea7 Lexical: Completed out table menu elements, logic pending 2024-08-03 18:01:54 +01:00
Dan Brown
a27a325af7 Lexical: Started on table actions
Started building table cell form/actions
2024-08-02 15:28:54 +01:00
Dan Brown
6b06d490c5 Lexical: Started table menu options
Updated UI elements to handle new scenarios needed in more complex table
menu
2024-08-02 11:16:54 +01:00
Dan Brown
13f8f39dd5 Lexical: Updated task list to use/support old format 2024-07-30 14:42:19 +01:00
Dan Brown
fe05cff64f Lexical: Linked up change/draft management 2024-07-29 21:43:20 +01:00
Dan Brown
d86837ac07 Lexical: Got working with attachment insert/drop 2024-07-29 21:14:42 +01:00
Dan Brown
9a7edc6e52 Lexical: Started drop handling, handled templates 2024-07-29 15:27:41 +01:00
Dan Brown
ce8c9dd079 Lexical: Added form complex/tab ui support 2024-07-28 12:48:58 +01:00
Dan Brown
c8f6b7e0d6 Lexical: Got media node core work & form done 2024-07-27 17:25:30 +01:00
Dan Brown
f284d31861 Lexical: Started media node support 2024-07-25 16:25:08 +01:00
Dan Brown
76b0d2d5d8 Lexical: Added common events support 2024-07-23 15:35:18 +01:00
Dan Brown
2cab778f19 Lexical: Improved table resize bars
Added scoll & page resize handling.
Added cropping/limiting to edit area.
2024-07-23 12:45:58 +01:00
Dan Brown
c31f8eb2e0 Readme: Added route4me sponsorship 2024-07-22 16:51:56 +01:00
Dan Brown
b618287585 Lexical: Added table toolbar, organised button code 2024-07-21 15:11:24 +01:00
Dan Brown
63f4b42453 Lexical: Added toolbar scroll/resize handling
Also added smarter above/below positioning to respond if toolbar would
be off the bottom of the editor, and added hide/show when they'd go
outside editor scroll bounds.
2024-07-19 18:12:51 +01:00
Dan Brown
c7c0df0964 Lexical: Finished up core drawing insert/editing
Added new options that sits on the context, for things needed but not
for the core editor, which are defined out of the editor (drawio URL,
error message text, pageId etc...)
2024-07-19 12:09:41 +01:00
Dan Brown
fb87fb5750 JS: Converted http service to ts 2024-07-18 15:13:14 +01:00
Dan Brown
634b0aaa07 Lexical: Started converting drawio to TS
Converted events service to TS as part of this.
2024-07-18 11:19:11 +01:00
Dan Brown
5002a89754 Lexical: Standardised helper function format 2024-07-17 16:45:57 +01:00
Dan Brown
b367490edc Lexical: Added list support, started todo 2024-07-17 16:38:20 +01:00
Dan Brown
e145f21512 Dev compose: Set image versions, removed unsupported mysql flag
Quick local test performed, ran a working instance.
For #5124
2024-07-17 11:13:39 +01:00
Dan Brown
ea4c50c2c2 Lexical: Added code block selection & edit features
Also added extra lifecycle handling for decorators to things can be
properly cleaned up after node destruction.
2024-07-16 16:36:08 +01:00
Dan Brown
d6021f4d22 Updated version and assets for release v24.05.3 2024-07-14 17:14:21 +01:00
Dan Brown
b9a3290731 Merge branch 'development' into release 2024-07-14 17:13:10 +01:00
Dan Brown
47ac0d5c3e Updated translator & dependency attribution before release v24.05.3 2024-07-14 17:09:41 +01:00
Dan Brown
75f225d6dc Updated translations with latest Crowdin changes (#5065) 2024-07-14 16:39:50 +01:00
Dan Brown
adb7bf7016 Codemirror: Enabled non-standard self-closing tags
For #5078
2024-07-14 16:36:36 +01:00
Dan Brown
897bb338f9 CSP: Updated handling of drawio URL to consider port
Previously if a custom port was used in the DRAWIO option it would not
be considered in the CSP handling, which would block loading.

Added test to cover.
For #5107
2024-07-14 16:06:18 +01:00
Dan Brown
767699a066 OIDC: Fixed incorrect detection of group detail population
An empty (but valid formed) groups list provided via the OIDC ID token
would be considered as a lacking detail, and therefore trigger a lookup
to the userinfo endpoint in an attempt to get that information.

This fixes this to properly distinguish between not-provided and empty
state, to avoid userinfo where provided as valid but empty.

Includes test to cover.
For #5101
2024-07-14 14:21:16 +01:00
Dan Brown
7161f22706 Dependancies: Updated composer & npm deps 2024-07-14 13:55:46 +01:00
Dan Brown
ddec8097b7 Merge pull request #5096 from DanielGordonIT/normalize-file-extensions
Wraps file extension comparison components in strtolower()
2024-07-14 13:51:55 +01:00
Dan Brown
95c3cc5c00 Styles: Improved callout RTL support
Will now adapt using logical styles where supported, will fallbacks
to old fixed LTR positioning where not supported.
For #5104
2024-07-14 12:21:07 +01:00
Dan Brown
60c53705ca Merge pull request #5069 from mueller-contria/5068-allowed_iframe_sources_in_phpunit_xml
Add ALLOWED_IFRAME_SOURCES to phpunit.xml
2024-07-14 12:06:17 +01:00
Dan Brown
51d8044a54 Lexical: Added initial form/modal styles 2024-07-09 20:49:47 +01:00
Dan Brown
ce697ab0f5 Readme: Added sponsor, removed road map section
Road map section was very much outdated and redundant so removing to
avoid confusion.
2024-07-09 14:37:29 +01:00
DanielGordonIT
ca310966b2 Actually add the test this time 2024-07-05 03:59:49 +00:00
DanielGordonIT
25f92ce584 Add test to verify different case on extensions works 2024-07-04 19:48:12 -04:00
Dan Brown
2c96af9aea Lexical: Worked on toolbar styling, got format submenu working 2024-07-04 16:16:16 +01:00
Dan Brown
04c7e680fd Lexical: Linked up saving logic of editor via interface 2024-07-04 13:09:53 +01:00
DanielGordonIT
9b0ef85f77 Wraps file extension comparison components in strtolower()
This avoids the issue where replacing file.PNG with newfile.png fails due to "PNG" not being equal to "png"
2024-07-03 15:50:25 -04:00
Dan Brown
a8f1160743 JS: Converted come common services to typescript 2024-07-03 11:00:57 +01:00
Dan Brown
feca1f0502 Lexical: Started diagram support 2024-07-03 10:28:04 +01:00
Dan Brown
d0a5a5ef37 Lexical: Linked code block to editor, added button 2024-07-02 17:34:03 +01:00
Dan Brown
97f570a4ee Lexical: Started code block node implementation 2024-07-02 14:46:30 +01:00
Dan Brown
9ebbf7ce94 Lexical: Started loading real content, Improved html loading
Added more styling/layout for buttons and main content area
2024-07-01 15:10:22 +01:00
Dan Brown
c2ecbf071f Lexical: Added tracked container, added fullscreen action
Changed how the editor is loaded in, so it now creates its own DOM, and
content is passed via creation function, to be better self-contained.
2024-07-01 10:44:23 +01:00
Dan Brown
b1c489090e Lexical: Added context toolbar placement, added link toolbar
Also added some basic context toolbar styling
2024-06-30 19:52:09 +01:00
Dan Brown
c9a03c5b01 Lexical: Added base context toolbar logic 2024-06-30 12:13:13 +01:00
Dan Brown
517c578a5f Lexical: Reorganised some logic into manager 2024-06-30 10:31:39 +01:00
Dan Brown
14837e34fb Readme: Added sponsor practinet 2024-06-28 22:28:06 +01:00
Dan Brown
f10ec3271a Lexical: Added overflow container 2024-06-27 16:28:06 +01:00
Dan Brown
4e2820d6e3 Lexical: Added horizontal rule node 2024-06-27 15:48:06 +01:00
Dan Brown
72a0e081ca Lexical: Completed initial table cell resize handle logic 2024-06-26 17:22:00 +01:00
Dan Brown
b1130cb1c3 Lexical: Linked up table resize handler (unfinished) 2024-06-26 13:52:00 +01:00
Dan Brown
59936631ec Lexical: Extracted mouse drag tracking to new helper 2024-06-25 18:33:29 +01:00
Dan Brown
3af22ce754 Lexical: Created custom table node with col width handling 2024-06-24 20:50:17 +01:00
Dan Brown
5546b8ff43 Lexical: Added more icons, made reflective text/bg color buttons 2024-06-23 15:50:41 +01:00
Dan Brown
a07092b7e6 Lexical: Updated lexical, added undo state tracking, format styles 2024-06-23 11:36:48 +01:00
Dan Brown
ac01c62e6e Lexical: Added table creator UI 2024-06-21 16:18:44 +01:00
Dan Brown
f47f7dd9d2 Lexical: Added base table support and started resize handling 2024-06-21 13:47:47 +01:00
Dan Brown
13d970c7ce Lexical: Added button icon system
With a bunch of default icons
2024-06-19 20:00:29 +01:00
Dan Brown
e2409a5fab Lexical: Added basic list button/support 2024-06-19 16:14:20 +01:00
Dan Brown
e30aae3399 Sponsors: Added Schroeck IT Consulting 2024-06-13 16:46:39 +01:00
Stefan Mueller
b81f2b52d0 Add ALLOWED_IFRAME_SOURCES to phpunit.xml
Fix for bug #5068
test_frame_src_csp_header_set fails, when .env-file has
customized ALLOWED_IFRAME_SOURCES
2024-06-13 12:41:05 +02:00
Dan Brown
9e43e03db4 Lexical: Added color picker controls 2024-06-12 19:51:42 +01:00
Dan Brown
a475cf68bf Lexical: Added clear formatting button 2024-06-12 14:24:50 +01:00
Dan Brown
e889bc680b Lexical: Added view/edit source code button/form/action 2024-06-12 14:01:36 +01:00
Dan Brown
48f235ea5a Updated version and assets for release v24.05.2 2024-06-10 11:44:06 +01:00
Dan Brown
047771b9f4 Merge branch 'development' into release 2024-06-10 11:43:05 +01:00
Dan Brown
c096b20d9c Updated translator & dependency attribution before release v24.05.2 2024-06-10 11:42:37 +01:00
Dan Brown
11a7ccc37e SAML: Set static type to pass static checks
Not totally clear if underlying code can actually return null, but
playing it safe to remain as-is for now for patch release.
2024-06-10 10:31:35 +01:00
Dan Brown
d9b9e6c0b1 Updated translations with latest Crowdin changes (#5022) 2024-06-10 10:16:34 +01:00
Dan Brown
f18d42f08e Merge pull request #5036 from bradenterpstra01/development
Fixed incorrect code shortcut reference
2024-06-09 23:23:28 +01:00
Dan Brown
4986f008b9 Merge pull request #5052 from michaelortnerit/development
Update docker-compose.yml
2024-06-09 23:20:01 +01:00
Dan Brown
a8ce199e0d Pages: Fixed unused changelog on first page publish
Included test to cover.
For #5056
2024-06-09 17:18:23 +01:00
Dan Brown
c77e8730d6 Deps: Updated php packages via composer 2024-06-09 17:03:29 +01:00
Dan Brown
3406846c82 Images: Updated GIF handling to use native methods
Changes GIF image thumbnail handling to direcly load via gd instead of
going through interventions own handling (which supports frames) since
we don't need animation for our thumbnails, and since performance issues
could arise with GIFs that have large frame counts.

For #5029
2024-06-09 17:00:58 +01:00
Dan Brown
bddc6ae66b Roles: Added max validation for role external auth id field
For #5037
2024-06-08 20:33:34 +01:00
Dan Brown
5c343638b6 Added base node/button for details/summary 2024-06-06 14:43:50 +01:00
Dan Brown
0722960260 Lexical: Added selection to state for aligned reading
Connected up to work with image form
2024-06-05 18:43:42 +01:00
Dan Brown
e959c468f6 Lexical: Made image resize handles functional 2024-06-05 17:18:58 +01:00
Dan Brown
ba871ec46a Lexical: Started image resize controls, Defined thorough decorator model 2024-06-05 13:04:49 +01:00
Michael Ortner
bd6e3c022f Update docker-compose.yml
Remove the version: because it is obsolete. See: https://docs.docker.com/compose/compose-file/04-version-and-name/#version-top-level-element-optional
2024-06-04 15:07:09 +02:00
Dan Brown
a74e04141c Lexical: Started build of image node and decoration UI 2024-06-03 16:56:31 +01:00
Dan Brown
7c504a10a8 Lexical: Created core modal functionality 2024-06-01 16:49:47 +01:00
Dan Brown
ae98745439 Lexical: Started on form UI 2024-05-30 16:50:55 +01:00
Dan Brown
57259aee00 Lexical: Added format previews to format buttons 2024-05-30 12:25:25 +01:00
bradenterpstra01
8759fff116 Update wysiwyg.blade.php
Remove the Shift for the numeric shortcut for incline code.

Ctrl+8 instead of Ctrl+Shift+8

I assume Mac is the same but I do not have a Mac to test with.
2024-05-29 18:01:48 -04:00
Dan Brown
dc1a40ea74 Lexical: Added ui container type
Structured UI logical to be fairly standard and mostly covered via
a base class that handles context and core dom work.
2024-05-29 20:38:31 +01:00
Dan Brown
483d9bf26c Lexical: Added a range of format buttons 2024-05-28 22:56:58 +01:00
Dan Brown
b24d60e98d Lexical: Started UI fundementals with basic button 2024-05-28 18:04:48 +01:00
Dan Brown
0f8bd869d8 Lexical: Added custom id-supporting paragraph blocks 2024-05-28 15:09:50 +01:00
Dan Brown
49546cd627 Lexical: Switched to ts for new editor build 2024-05-27 23:50:28 +01:00
Dan Brown
6e852d2e65 Lexical: Played with commands, extracted & improved callout node 2024-05-27 20:23:45 +01:00
Dan Brown
5a4f595341 Editors: Added lexical editor for testing
Started basic playground for testing lexical as a new WYSIWYG editor.
Moved out tinymce to be under wysiwyg-tinymce instead so lexical is the
default, but TinyMce code remains.
2024-05-27 15:39:41 +01:00
Dan Brown
6019d2ee14 MFA: Tweaked backup code wording
It was not clear before as it could be taken that the system would
securely store the codes.

Closes #5017
2024-05-23 11:30:53 +01:00
Dan Brown
b5375114d3 Updated version and assets for release v24.05.1 2024-05-21 11:07:36 +01:00
Dan Brown
fc13e56cea Merge branch 'development' into release 2024-05-21 11:07:10 +01:00
Dan Brown
f937bf3abb Updated translator & dependency attribution before release v24.05.1 2024-05-21 11:06:08 +01:00
Dan Brown
586e8963a8 Updated translations with latest Crowdin changes (#4994) 2024-05-21 11:04:27 +01:00
Dan Brown
bdfa76ed9a Deps: Updated php/composer packages 2024-05-20 17:28:53 +01:00
Dan Brown
d133f904d3 Auth: Changed email confirmations to use login attempt user
Negates the need for a public confirmation resend form
since we can instead just send direct to the last session login attempter.
2024-05-20 17:23:15 +01:00
Dan Brown
69af9e0dbd Routes: Added throttling to a range of auth-related endpoints
Some already throttled in some means, but this adds a simple ip-based
non-request-specific layer to many endpoints.
Related to #4993
2024-05-20 14:00:58 +01:00
Dan Brown
72c5141dec File Uploads: Added basic validation response formatting
Tested via app-level validation file limit, and then also with nginx
file post limit.
For #4996
2024-05-18 21:18:15 +01:00
Dan Brown
5651d2c43d Config: Reverted change to cache directory
Change made during Laravel 10 updates to align (Laravel made this change
much earlier in 5.x series) but it caused issues due to folder not
pre-existing and due to potentiall permission issues.
(CLI could create this during update, with non-compatible permissions
for webserver).

For #4999
2024-05-18 20:40:26 +01:00
Dan Brown
fc236f930b Dark Mode: Fixed setting labels missing dark mode handling
Fixes #5018
2024-05-18 20:37:49 +01:00
Dan Brown
570af500f4 WYSIWYG: Added justify cell range cleanup
To help override & gain control of setting text alignment in tables.

- Adds support of clearing "align" attributes in certain operations.
- Updates cell range action handling to dedupe execcommand handling.
- Adds clearing of additional alignment classes on direction control.

Closes #5011
2024-05-16 14:59:30 +01:00
Dan Brown
38913288d8 Devdocs: Fixed visual theme system lang folder reference
Made some other minor updates while there.
Fixes #4998
2024-05-16 14:15:26 +01:00
Dan Brown
c14d7d9509 Merge pull request #5008 from KiDxS/fix-notification-preferences-url-in-email
Fixed notification preferences URL in email
2024-05-16 14:11:15 +01:00
Angelo Geant Gaviola
79f5be4170 Fixed notification preferences URL in email 2024-05-14 17:04:23 +08:00
Dan Brown
77fc37ac25 Updated version and assets for release v24.05 2024-05-11 15:49:29 +01:00
Dan Brown
3424351e84 Merge branch 'development' into release 2024-05-11 15:48:49 +01:00
Dan Brown
a3a776d4a6 Updated translator & dependency attribution before release v24.05 2024-05-11 15:47:38 +01:00
Dan Brown
2b9b0f91cb Updated translations with latest Crowdin changes (#4890) 2024-05-11 15:15:10 +01:00
Dan Brown
424e8f503e Readme: Updated sponsor list 2024-05-10 11:02:20 +01:00
Dan Brown
d206129f3d Deps: Updated composer dependencies 2024-05-05 16:30:04 +01:00
Dan Brown
baad7fa9cb Merge pull request #4987 from BookStackApp/audit_api
Addition of Audit Log API Endpoint
2024-05-05 16:14:09 +01:00
Dan Brown
d54c7b4783 Audit Log: Fixed bad reference to linked entity item 2024-05-05 16:05:21 +01:00
Dan Brown
67df127c26 API: Added to, and updated, testing to cover audit log additions 2024-05-05 15:44:58 +01:00
Dan Brown
3946158e88 API: Added audit log list endpoint
Not yested covered with testing.
Changes database columns for more presentable names and for future use
to connect additional model types.
For #4316
2024-05-04 16:28:18 +01:00
Dan Brown
dd251d9e62 Merge branch 'nesges/development' into development 2024-05-04 14:00:40 +01:00
Dan Brown
5c28bcf865 Registration: Reviewed added simple honeypot, added testing
Also cleaned up old RegistrationController syntax.
Review of #4970
2024-05-04 13:59:41 +01:00
Dan Brown
7b3b28d3f8 Merge pull request #4972 from johnroyer/fix-typo-in-language-file
remove space at the beginning of description
2024-05-03 19:16:23 +01:00
Dan Brown
20e86bf376 Merge branch 'development' of github.com:BookStackApp/BookStack into development 2024-05-03 13:40:18 +01:00
Dan Brown
f9e087330b WYSIWYG: Added text direction support for code editor popup
Editor popup will now reflect the direction of the opened code block.
This also updates in-editor codemirror instances to correcly reflect/use
the direction if set on the inner code elem.

This also defaults new code blocks, when in RTL languages, to be started
in LTR, which can then be changed via in-editor direction controls if
needed. This is on the assumption that most code will be LTR (could not
find much examples of RTL code use).

Fixes #4943
2024-05-03 13:40:00 +01:00
Dan Brown
b0720777be Merge pull request #4985 from BookStackApp/ldap_ca_cert_control
LDAP CA TLS Cert Option, PR Review and continuation
2024-05-02 23:16:16 +01:00
Dan Brown
8087123f2e LDAP: Review, testing and update of LDAP TLS CA cert control
Review of #4913
Added testing to cover option.
Updated option so it can be used for a CA directory, or a CA file.
Updated option name to be somewhat abstracted from original underling
PHP option.

Tested against Jumpcloud.
Testing took hours due to instability which was due to these settings
sticking and being unstable on change until php process restart.
Also due to little documentation for these options.
X_TLS_CACERTDIR option needs cert files to be named via specific hashes
which can be achieved via c_rehash utility.

This also adds detail on STARTTLS failure, which took a long time to
discover due to little detail out there for deeper PHP LDAP debugging.
2024-05-02 23:11:31 +01:00
Dan Brown
4c1c315594 WYSWIYG: Fixed misaligned table cell p line height
Removes an editor-specific line-height which was overriding cell
paragraph line height, causing mis-aligned style compared to viewing.
Checked a range of styles and looked at history, could not see original
purpose of the line-height removed here.
Closes #4960
2024-05-02 15:20:51 +01:00
Dan Brown
f95fb640af WYSWIYG: Improved use of object tags to embed content
- Prevented image toolbars showing for objects embeds due to tinymce
  image placeholder, and added media toolbar.
- Fixed height of object embed placeholder being forced to auto
  when in the editor, allowing height attributed to be properly
  reflected as it would on normal page view.

Closes #4974
2024-05-01 17:22:53 +01:00
Dan Brown
493d8027cd Attachments: Fixed drag into editor in Chrome
Seemed to be chrome specific from testing.
Required editors to have preventDefault called on dragover.
Tested in Chrome, FF, & Safari.
Tested in both editors, and re-tested text/image drop to ensure still
works.

Fixed #4975
2024-04-29 19:21:13 +01:00
Dan Brown
06bb55184c WYSIWYG: Fixed unexpected clearing of table cell styles
Fixes custom table cell clear-format handling since it was being called
on many format removals, not just the clear-formatting action.
This updates the code to specifically run on the RemoveFormat action
which is triggered by the clear formatting button.
Fixes #4964
2024-04-29 17:47:06 +01:00
Dan Brown
6b681961e5 LDAP: Updated default user filter placeholder format
To not conflict with env variables, and to align with placeholders used
for PDF gen command.
Added test to cover, including old format supported for
back-compatibility.
For #4967
2024-04-28 12:29:57 +01:00
Dan Brown
e1149a27e9 Merge pull request #4969 from BookStackApp/pdf_command_option
PDF Exports: New command option and library/option cleanup
2024-04-26 17:06:38 +01:00
Dan Brown
f0dd33c1b4 PDF: Added tests for pdf command, fixed old tests for changes 2024-04-26 15:39:40 +01:00
Zero
5860e1e2ce remove space at the beginning of description 2024-04-25 13:35:36 +08:00
Dan Brown
1c7128c2cb PDF: Added implmentation of command PDF option
Tested quickly manually but not yet covered by PHPUnit tests.
2024-04-24 16:09:53 +01:00
Dan Brown
40200856af PDF: Removed barryvdh snappy to use snappy direct
Also simplifies config format, and updates snappy implmentation to use
the new config file.
Not yet tested.
2024-04-24 15:13:44 +01:00
Dan Brown
bb6670d395 PDF: Started new command option, merged options, simplified dompdf
- Updated DOMPDF to direcly use library instead of depending on barry
wrapper.
- Merged existing export options file into single exports file.
- Defined option for new command option.

Related to #4732
2024-04-22 16:40:42 +01:00
nesges
0d2a268be0 whitespace only 2024-04-21 17:44:01 +02:00
nesges
16399b63be better accessibility for honepot formfield 2024-04-21 16:08:28 +02:00
Dan Brown
d949b97cc1 Merge pull request #4955 from BookStackApp/oidc_userinfo
OIDC userinfo endpoint support
2024-04-19 16:55:29 +01:00
Dan Brown
8b14a701a4 OIDC Userinfo: Fixed issues with validation logic from changes
Also updated test to suit validation changes
2024-04-19 16:43:51 +01:00
Dan Brown
0958909cd9 OIDC Userinfo: Added additional tests to cover jwks usage 2024-04-19 15:05:00 +01:00
Dan Brown
b18cee3dc4 OIDC Userinfo: Added JWT signed response support
Not yet tested, nor checked all response validations.
2024-04-19 14:12:27 +01:00
nesges
31272e60b6 add ambrosia-container to registration form as honeypot for bots: new form field "username" must not be filled 2024-04-19 09:35:09 +02:00
nesges
1b1cb18839 fixed mislabeling of name input 2024-04-19 09:18:34 +02:00
Dan Brown
fa543bbd4d OIDC Userinfo: Started writing tests to cover userinfo calling 2024-04-17 23:26:56 +01:00
Dan Brown
7d7cd32ca7 OIDC Userinfo: Added userinfo data validation, seperated from id token
Wrapped userinfo response in its own class for additional handling and
validation.
Updated userdetails to take abstract claim data, to be populated by
either userinfo data or id token data.
2024-04-17 18:23:58 +01:00
Dan Brown
a71c8c60b7 OIDC: Extracted user detail handling to own OidcUserDetails class
Allows a proper defined object instead of an array an extracts related
logic out of OidcService.
Updated userinfo to only be called if we're missing details.
2024-04-16 18:14:22 +01:00
Dan Brown
9183e7f2fe OIDC Userinfo: Labelled changes to be made during review 2024-04-16 15:52:55 +01:00
Dan Brown
d640411adb OIDC: Cleaned up provider settings, added extra validation
- Added endpoint validation to ensure HTTPS as per spec
- Added some missing types
- Removed redirectUri from OidcProviderSettings since it's not a
  provider-based setting, but a setting for the oauth client, so
  extracted that back to service.
2024-04-16 15:19:51 +01:00
Dan Brown
dc6013fd7e Merge branch 'development' into lukeshu/oidc-development 2024-04-16 14:57:36 +01:00
Dan Brown
80ac66e0a6 Code Editor: Added scala to language list
For #4953
2024-04-16 14:44:17 +01:00
Dan Brown
f05ec4cc26 Tags: Stopped recycle bin tags being counted on index
For #4892
Added test to cover.
2024-04-15 18:44:59 +01:00
Dan Brown
d9ff001ffe Merge pull request #4904 from C0rn3j/optimize-images
15KB lossless optimization via oxipng(PNG) and svgo(SVG)
2024-04-15 18:07:29 +01:00
Dan Brown
0f6cb9ed84 Content styles: Made links underlined for visibility
Inline with A11y recommendations where color may not be reliable on its
own.
Tested various content link scenarios across chrome, safari & FF.
For #4939
2024-04-13 15:48:39 +01:00
Dan Brown
dde1f27882 Merge pull request #4930 from BookStackApp/split_md_js
JS Build: Split markdown to own file, updated packages
2024-04-08 14:46:06 +01:00
Dan Brown
f5e6f9574d JS Build: Split markdown to own file, updated packages
Markdown-related code was growing, representing half of app.js main
bundle code while only being needed in one view/scenario.
This extracts markdown related code to its own built file.
Related to #4858
2024-04-08 14:41:51 +01:00
Dan Brown
ee40adf11a Merge pull request #4921 from BookStackApp/v24-02
v23.02.3 changes
2024-04-05 15:21:05 +01:00
Dan Brown
606f9d92d0 Updated version and assets for release v24.02.3 2024-04-05 15:20:08 +01:00
Dan Brown
a5e25abb9c Merge branch 'v24-02' into release 2024-04-05 15:19:34 +01:00
Dan Brown
3e23f456fe CSS: Removed redundant calc 2024-04-05 15:18:58 +01:00
Dan Brown
b9e2d33ed4 Page Content: Aligned max-width across viewer and editors
For #4916
2024-04-05 15:06:08 +01:00
Dan Brown
19f78dbe6c WYSIWYG descriptions: Allowed anchor target attrs
Allowed since this is a control in the editor UI, but would previously
be stripped by editor config & server-side filtering.
For #4925
2024-04-03 16:46:53 +01:00
Dan Brown
a33dbcb04a References: Fixed references count/list recycle bin interaction
Count and reference list would get references then attempt to load
entities, which could fail to load if in the recycle bin.
This updates the queries to effectively ignore references for items we
can't see (in recycle bin).
Added test to cover.

For #4918
2024-04-01 17:08:53 +01:00
Dan Brown
58f6219cb3 Code: Fixed highlighting issues when no code language set
For #4917
2024-03-31 14:33:08 +01:00
Matt Moore
18269f2c60 Add LDAP_TLS_CACERTFILE to example env file 2024-03-27 13:17:25 +00:00
Matt Moore
06ef95dc5f Change to allow override of CA CERT for LDAPS
Using the env LDAP_TLS_CACERTFILE to set a file to use to override
the CA CERT used to verify LDAPS connections. This is to make this
process easier for docker use.
2024-03-26 16:30:04 +00:00
Martin Rys
76c7166268 Use zopfli for oxipng for extra 3KB~ 2024-03-26 12:31:54 +01:00
Dan Brown
6c063f424c Merge pull request #4907 from BookStackApp/licensing_update
Dependency Licensing Improvements
2024-03-24 12:01:01 +00:00
Dan Brown
3345680f7d Licensing: Added license gen as composer command 2024-03-24 11:58:31 +00:00
Dan Brown
a2fd80954b Licensing: Added links and tests for new licenses endpoint
For #4907
2024-03-23 22:04:18 +00:00
Dan Brown
0c524c7c8f Licensing: Added licenses app view
Extracted many methods to a new "MetaController" in the process.
2024-03-23 16:31:13 +00:00
Martin Rys
5f306a11e7 15KB lossless optimization via oxipng(PNG) and svgo(SVG) 2024-03-23 16:33:11 +01:00
Dan Brown
ed956a4cf0 Licensing: Updated license gen scripts to share logic 2024-03-23 15:33:05 +00:00
Dan Brown
55a2a6db88 Licensing: Added script to gen info for JS packages 2024-03-23 15:19:58 +00:00
Dan Brown
f789359886 Licensing: Added script to build PHP library licensing information 2024-03-22 14:44:23 +00:00
Dan Brown
c221a00e1e Migrations: Added prefix support to schema inspection 2024-03-19 10:30:26 +00:00
Dan Brown
83913af68b Merge branch 'development' into C0rn3j/development 2024-03-18 14:35:16 +00:00
Dan Brown
fa5395a02b Meta: Updated workflows, licence and readme
- Updated license year
- Updated some readme wording, removed lapsed sponsor, Removed twitter
  link, added link to alt github source
- Update cache action for GH workflows since GH was complaining
2024-03-18 14:26:31 +00:00
Dan Brown
85dd71507e Merge pull request #4903 from BookStackApp/laravel10
Framework: Upgrade from Laravel 9 to 10
2024-03-17 17:00:03 +00:00
Dan Brown
28d6292278 Framework: Addressed deprecations 2024-03-17 16:52:19 +00:00
Dan Brown
b4b84f81a0 Deps: Updated custom symfony/mailer package
Done during #4903 work
2024-03-17 16:32:59 +00:00
Dan Brown
2345fd4677 Deps: Updated intervention library from 2 to 3
Major version change, required some changes to API
For #4903
2024-03-17 16:03:12 +00:00
Dan Brown
3250fc732c Testing: Updated PHPUnit from 9 to 10
For #4903
2024-03-17 15:41:11 +00:00
Dan Brown
45d52f27ae Migrations: Updated with type hints instead of php doc
Also updated code to properly import used facades.
For #4903
2024-03-17 15:29:09 +00:00
Dan Brown
d6b7717985 Framework: Fixed issues breaking tests
For #4903
2024-03-16 15:26:34 +00:00
Dan Brown
794671ef32 Framework: Upgrade from Laravel 9 to 10
Following Laravel guidance and GitHub diff.
Not yet in tested state with app-specific changes made.
2024-03-16 15:12:14 +00:00
Martin Rys
70479df5dc Dockerfile: Don't cache 50MB of lists and use a single layer, make it pretty 2024-03-12 14:04:33 +01:00
Dan Brown
07761524af Dev: Fixed flaky OIDC test, updated dev version 2024-03-12 12:08:26 +00:00
Dan Brown
2ed931aeed Updated minimum PHP version from 8.0 to 8.1
For #4893
2024-03-12 11:29:51 +00:00
Dan Brown
b310e87e4c Updated version and assets for release v24.02.2 2024-03-11 14:30:48 +00:00
Dan Brown
425baf9d6e Merge branch 'development' into release 2024-03-10 18:46:05 +00:00
Dan Brown
0d3de40459 Updated translator attribution before release v24.02.1 2024-03-10 18:45:32 +00:00
Dan Brown
3619f79ca6 Updated translations with latest Crowdin changes (#4877) 2024-03-10 18:36:12 +00:00
Dan Brown
c9d9ad10f2 Merge branch 'totp-patch' into development 2024-03-10 18:32:02 +00:00
Dan Brown
d5a689366c MFA: Copied autocomplete changes from totp to backup codes
Also added tests to cover.
Related to #4849
2024-03-10 18:31:01 +00:00
Dan Brown
bc24a1360f TOTP: Added one-time-code autofill
During review of #4849
Tested on Firefox & Chromium desktop.
2024-03-10 18:24:42 +00:00
Dan Brown
77f125208e Page nav: Fixed nbsp being represented as nothing
Now represented in page nav using a normal space to avoid complete
removal of space.
Added test to cover.
For #4836
2024-03-09 15:52:09 +00:00
Dan Brown
b7d4bd5bce Breadcrumbs: Set book/shelf lists to use name ordering
Previously in database order (id) which is not predictable
nor parsable for users.
For #4876
2024-03-09 15:24:44 +00:00
Dan Brown
5a5f0b8de9 Page Display: Fixed highlighting for elements in nested details
For #4878
2024-03-09 15:07:51 +00:00
Dan Brown
825c369ad9 Updated version and assets for release v24.02 2024-02-28 13:35:36 +00:00
Dan Brown
10bab70438 Merge branch 'development' into release 2024-02-28 13:35:23 +00:00
Dan Brown
8e01345f14 Entity popular queriy: Loaded parents for selector breadcrumbs 2024-02-28 13:20:24 +00:00
Dan Brown
f5f96f84e7 404: Fixed entity list issue with entity with non-visible parent
Adds our mixed entity list loader to popular queries for more efficient
loading.
2024-02-28 13:08:06 +00:00
Dan Brown
2009d4d6a8 Translations: Updated translator attribution, added serbian to locales 2024-02-28 12:29:09 +00:00
Dan Brown
4ccfde6d02 Updated translations with latest Crowdin changes (#4803) 2024-02-28 12:19:36 +00:00
Dan Brown
c4279c9697 Merge branch 'v23-12' into development
Updated composer deps again to take lock file to current
2024-02-28 12:11:39 +00:00
Dan Brown
350e0b281b Updated version and assets for release v23.12.3 2024-02-26 12:05:02 +00:00
Dan Brown
08805ea3c8 Merge branch 'v23-12' into release 2024-02-26 12:04:25 +00:00
Dan Brown
48ea0bc291 Deps: Updated composer packages 2024-02-26 11:17:36 +00:00
Dan Brown
a75d5b8bc1 Sessions: Prevent image urls being part of session URL history
To prevent them being considered for redirects.
Includes test to cover.
For #4863
2024-02-22 11:23:59 +00:00
Dan Brown
055bbf17de Theme System: Added AUTH_PRE_REGISTER logical event
Included tests to cover.
Manually tested on standard and social (GitHub) auth.
For #4833
2024-02-21 15:30:29 +00:00
Dan Brown
be3423a16e Deps: Updated npm & composer deps
Avoided updating markdown-it package to 14 for now since it would cause
bundle size to inflate. Don't think ESBuild is properly tree shaking
"entities" sub package which inflates size.
(Copied this message from december deps update).
2024-02-20 18:21:59 +00:00
Dan Brown
bbb41e8b5c Breadcrumbs: Fixed bad dropdown menu placement at small sizes
For #4824
2024-02-20 18:03:32 +00:00
Dan Brown
c290d01adb WYSIWYG: Improved a range of text direction/alignment scenarios
- Removes 'span' from being a valid part of alignment formats so it's
  not used to align contents, since it's going to mostly be an inline
  format, wheras you'd really want alignment on the parent block.
- Adds direction cleaning to all direction change events, to remove
  direction styles and child direction controls which may complicate
  matters and cause direction changes not to show.
- Makes text direction controls work with table cell range selections,
  which TinyMCE does not consider by default, via manual handling.

For #4843
2024-02-20 14:15:22 +00:00
Dan Brown
16327cf40c Cover images: Updated description wording to better detail size
To make it clearer that the advised size may not be fixed.
For #4748
2024-02-19 20:26:04 +00:00
Dan Brown
999d41a7f5 WYSIWYG: Updated code handling to respect direction
Specifically supports "dir" attribute being on top level "pre" element,
and handles application/switching of this within the editor.

For #4809
2024-02-18 17:55:56 +00:00
Dan Brown
9ff9b9c805 Merge pull request #4850 from BookStackApp/table_improvements
Range of WYSIWYG Editor Table Handling Improvements
2024-02-17 16:40:27 +00:00
Dan Brown
8f1d8cef9e Tables: Added dynamic table header toggle
Shows in table context toolbar when in the first row.
2024-02-17 16:28:13 +00:00
Dan Brown
8688ad99b6 Tables: Added menu items to clear formatting and sizes 2024-02-16 14:38:30 +00:00
Dan Brown
ed0718d3f7 Tables: Added fix to ensure proper clear formatting on cell selections 2024-02-15 16:29:37 +00:00
Mattic
c53c9f6866 Turned off autocomplete for TOTP codes
Small QOL change to turn off autocomplete when entering TOTP codes since they're one time use only.
2024-02-15 09:22:35 -06:00
Dan Brown
3fdee6a93b Tables: Updated selection style to avoid scroll overflow
Fixes #4844
2024-02-15 14:40:27 +00:00
Dan Brown
cafea1c02d Updated tinymce from 6.7.2 to 6.8.3 2024-02-15 14:13:08 +00:00
Dan Brown
32e20e5059 Merge branch 'development' of github.com:BookStackApp/BookStack into development 2024-02-14 10:36:36 +00:00
Dan Brown
c66b8ad842 RTL: Fixed pagination not responding to RTL layout
For #4808
2024-02-14 10:36:00 +00:00
Dan Brown
c9a5c29abf Merge pull request #4794 from BookStackApp/en_tweaks
Text: Tweaks to EN text for consistency/readability
2024-02-13 14:13:29 +00:00
Dan Brown
12daa1c2b9 Header: Fixed mobile menu falling out of header
Changed button to be within-DOM rather than absolute positioned.
Also improves RTL handling by showing menu on the right side.

Fixes #4841
2024-02-13 14:00:34 +00:00
Dan Brown
ff8daad22b Merge pull request #4827 from BookStackApp/query_revamp
Update of entity loading to be more efficient and avoid global addSelects
2024-02-11 15:56:32 +00:00
Dan Brown
1ea2ac864a Queries: Update API to align data with previous versions
Ensures fields returned match API docs and previous versions of
BookStack where we were accidentally returning more fields than
expected.
Updates tests to cover many of these.
Also updated clockwork to ignore image requests for less noisy
debugging.
Also updated chapter page query to not be loading all page data, via new
query in PageQueries.
2024-02-11 15:42:37 +00:00
Dan Brown
ed9c013f6e Queries: Addressed failing test cases from recent changes 2024-02-08 17:18:03 +00:00
Dan Brown
ed21a6d798 Queries: Updated old use-specific entity query classes
- Updated name to align, and differentate from new 'XQueries' clases.
- Removed old sketchy base class with app resolving workarounds, to a
  proper injection-based approach.
- Also fixed wrong translation text used in PageQueries.
2024-02-08 16:39:59 +00:00
Dan Brown
b77ab6f3af Queries: Moved out or removed some class-level items
Also ran auto-removal of unused imports across app folder.
2024-02-07 22:41:45 +00:00
Dan Brown
546cfb0dcc Queries: Extracted static page,chapter,shelf queries to classes 2024-02-07 21:58:27 +00:00
Dan Brown
483410749b Queries: Updated all app book static query uses 2024-02-07 16:37:36 +00:00
Dan Brown
c95f4ca40f Queries: Migrated revision repo queries to new class 2024-02-07 15:09:16 +00:00
Dan Brown
222c665018 Queries: Extracted PageRepo queries to own class
Started new class for PageRevisions too as part of these changes
2024-02-05 17:35:49 +00:00
Dan Brown
8e78b4c43e Queries: Extracted chapter repo queries to class
Updated query classes to align to interface for common aligned
operations.
Extracted repeated string-identifier-based finding from page/chapter
repos to shared higher-level entity queries.
2024-02-05 15:59:20 +00:00
Dan Brown
05ac0fcd1d Merge pull request #4828 from shashinma/development
Update PWA manifest orientation from 'portrait' to 'any'
2024-02-05 11:54:32 +00:00
Mikhail Shashin
9fa68fd8ab Update PWA manifest orientation to any
Changed the orientation settings in PwaManifestBuilder.php from 'portrait' to 'any'. This allows the PWA to adjust to any screen orientation, enhancing user flexibility.
2024-02-05 04:28:22 +03:00
Dan Brown
3886aedf54 Queries: Migrated bookshelf repo queries to new class 2024-02-04 19:32:19 +00:00
Dan Brown
1559b0acd1 Queries: Migrated BookRepo queries to new query class
Also moved to a non-static approach, and added a high-level class to
allow easy access to all other entity queries, for use in mixed-entity
scenarios and easier/simpler injection.
2024-02-04 17:35:16 +00:00
Dan Brown
a70ed81908 DB: Started update of entity loading to avoid global selects
Removes page/chpater addSelect global query, to load book slug, and
instead extracts base queries to be managed in new static class, while
updating specific entitiy relation loading to use our more efficient
MixedEntityListLoader where appropriate.

Related to #4823
2024-02-04 14:39:36 +00:00
Dan Brown
2460e7c56e Plonker Remediation: Removed dd line left in from debugging 2024-02-01 12:57:26 +00:00
Dan Brown
779f09bff6 Merge branch 'chapter-templates' into development 2024-02-01 12:55:38 +00:00
Dan Brown
43a72fb9a5 Default chapter templates: Added tests, extracted repo logic
- Updated existing book tests to be generic to all default templates,
  and updated with chapter testing.
- Extracted repeated logic in the Book/Chapter repos to be shared in the
  BaseRepo.

Review of #4750
2024-02-01 12:51:47 +00:00
Dan Brown
4137cf9c8f Default chapter templates: Updated api docs and tests
Also applied minor tweaks to some wording and logic.

During review of #4750
2024-02-01 12:22:16 +00:00
Dan Brown
16af833124 Merge pull request #4815 from BookStackApp/comment_wysiwyg
Comment WYSIWYG Inputs
2024-01-31 16:57:36 +00:00
Dan Brown
47f082c085 Comments: Added HTML filter test, fixed placeholder in dark mode 2024-01-31 16:47:58 +00:00
Dan Brown
fee9045dac Comments: Removed remaining uses of redundant 'text' field
Opened #4821 to remove the DB field in a few releases time.
2024-01-31 16:35:58 +00:00
Dan Brown
06901b878f Comments: Added HTML filter on load, tinymce elem filtering
- Added filter on load to help prevent potentially dangerous comment
  HTML in DB at load time (if it gets passed input filtering, or is
  existing).
- Added TinyMCE valid_elements for input wysiwygs, to gracefully degrade
  content at point of user-view, rather than surprising the user by
  stripping content, which TinyMCE would show, post-save.
2024-01-31 16:20:22 +00:00
Dan Brown
e9a19d5878 Comments: Added wysiwyg link selector, updated tests, removed command
- Updated existing tests with recent back-end changes, mainly to use
  HTML data.
- Removed old comment regen command that's no longer required.
2024-01-31 14:22:04 +00:00
Dan Brown
adf0baebb9 Comments: Added back-end HTML support, fixed editor focus
Also fixed handling of editors when moved in DOM, to properly remove
then re-init before & after move to avoid issues.
2024-01-30 15:16:58 +00:00
Dan Brown
5c92b72fdd Comments: Added input wysiwyg for creating/updating comments
Not supporting old content, existing HTML or updating yet.
2024-01-30 14:27:09 +00:00
Dan Brown
24e6dc4b37 WYSIWYG: Altered how custom head added to editors
Updated to parse and add as DOM nodes instead of innerHTML to avoid
triggering an update of all head content, which would throw warnings in
chromium in regard to setting the base URI.

For #4814
2024-01-30 11:38:47 +00:00
Sascha
4a8f70240f added template to chapter API controller 2024-01-29 19:59:03 +01:00
Sascha
64c783c6f8 extraded template form to own file and changed translations 2024-01-29 19:55:39 +01:00
Sascha
2a849894be Update entities.php
changed text of `pages_delete_warning_template` to include chapters
2024-01-29 19:37:59 +01:00
Dan Brown
415663a9bc Merge pull request #4804 from BookStackApp/oidc_pkce
Add OIDC PKCE functionality
2024-01-27 18:11:19 +00:00
Dan Brown
1dc094ffaf OIDC: Added testing of PKCE flow
Also compared full flow to RFC spec during this process
2024-01-27 16:41:15 +00:00
Dan Brown
3e9e196cda OIDC: Added PKCE functionality
Related to #4734.
Uses core logic from League AbstractProvider.
2024-01-25 14:24:46 +00:00
Dan Brown
5903823eed Merge pull request #4796 from BookStackApp/v23-12
Merge in v23.12.2 changes
2024-01-24 10:38:14 +00:00
Dan Brown
9441e32c69 Updated version and assets for release v23.12.2 2024-01-24 10:37:20 +00:00
Dan Brown
530fc37067 Merge branch 'v23-12' into release 2024-01-24 10:36:52 +00:00
Dan Brown
8fb9d9d4c2 Dependancies: Updated PHP deps via composer 2024-01-24 10:27:09 +00:00
Dan Brown
eff7aa0f73 Updated translator attribution before v23.12.2 release 2024-01-24 10:25:24 +00:00
Dan Brown
14ecb19b05 Merged l10n_development into v23-12
Squash merge
Closes #4779
2024-01-24 10:23:09 +00:00
Sascha
0fc02a2532 fixed error from phpcs 2024-01-23 22:37:15 +01:00
Sascha
8c6b116472 Update TrashCan.php
remove duplicate call of $page->forceDelete();
2024-01-23 21:37:00 +01:00
Dan Brown
69c8ff5c2d Entity selector: Fixed initial load overwriting initial search
This changes how initial searches can be handled via config rather than
specific action so they can be considered in how the initial data load
is done, to prevent the default empty state loading and overwriting the
search data if it lands later (which was commonly likely).

For #4778
2024-01-23 15:42:13 +00:00
Dan Brown
788327fffb Attachment List: Fixed broken ctrl-click functionality
Fixes #4782
2024-01-23 15:01:07 +00:00
Dan Brown
655ae5ecae Text: Tweaks to EN text for consistency/readability
As suggested by Tim in discord chat.
2024-01-23 12:31:44 +00:00
Dan Brown
d5a91d0d35 Merge pull request #4758 from BookStackApp/range_request_support
Range request support
2024-01-17 11:10:38 +00:00
Dan Brown
369e499dce Updated version and assets for release v23.12.1 2024-01-16 12:16:06 +00:00
Dan Brown
655815de6d Merge branch 'development' into release 2024-01-16 12:15:50 +00:00
Dan Brown
a4fd825fe2 Merge branch 'development' of github.com:BookStackApp/BookStack into development 2024-01-16 12:14:44 +00:00
Dan Brown
496b4264d9 Updated translator attribution 2024-01-16 12:14:25 +00:00
Dan Brown
57284bb869 Updated translations with latest Crowdin changes (#4747) 2024-01-16 12:10:22 +00:00
Dan Brown
adf1806fea Chapters API: Added missing book_slug field
Was removed during previous changes, but reflected in response examples.
This adds into all standard single chapter responses.
For #4765
2024-01-16 12:06:13 +00:00
Dan Brown
2dc454d206 Uploads: Explicitly disabled s3 streaming in config
This was the default option anyway, just adding here for
better visibility of this being set.
Can't enable without issues as the app will attempt to seek which does
not work for these streams. Also have not tested on non-s3, s3-like
systems.
2024-01-15 13:36:04 +00:00
Dan Brown
c1552fb799 Attachments: Drag and drop video support
Supports dragging and dropping video attahchments to embed them in the
editor as HTML video tags.
2024-01-15 11:57:20 +00:00
Dan Brown
91d8d6eaaa Range requests: Added test cases to cover functionality
Fixed some found issues in the process.
2024-01-14 15:50:00 +00:00
Dan Brown
afbbcafd44 Readme: Updates sponsor list 2024-01-10 14:33:49 +00:00
Dan Brown
d94762549a Range requests: Added basic HTTP range support 2024-01-07 20:34:03 +00:00
Dan Brown
b4d9029dc3 Range requests: Extracted stream output handling to new class 2024-01-07 14:03:13 +00:00
Sascha
70bfebcd7c Added Default Templates for Chapters 2024-01-01 21:58:49 +01:00
Dan Brown
457adc1fee Updated version and assets for release v23.12 2023-12-29 12:16:07 +00:00
Dan Brown
e86a90967e Merge branch 'development' into release 2023-12-29 12:15:34 +00:00
Dan Brown
b191d8f99f Updated translator attribution before release v23.12 2023-12-29 12:08:39 +00:00
Dan Brown
c017f5bed1 Updated translations with latest Crowdin changes (#4658) 2023-12-28 17:49:38 +00:00
Dan Brown
5b1929a39a Languages: Added Finnish to language list 2023-12-28 15:24:51 +00:00
Dan Brown
02d94c8798 Permissions: Updated generation querying to be more efficient
Query of existing entity permissions during view permission generation
could cause timeouts or SQL placeholder limits due to massive whereOr
query generation, where an "or where" clause would be created for each
entity type/id combo involved, which could be all within 20 books.

This updates the query handling to use a query per type involved, with
no "or where"s, and to be chunked at large entity counts.

Also tweaked role-specific permission regen to chunk books at
half-previous rate to prevent such a large scope being involved on each
chunk.

For #4695
2023-12-23 13:35:57 +00:00
Dan Brown
88ee33ee49 Deps: Updated php depenencies via composer 2023-12-22 15:48:46 +00:00
Dan Brown
529f7bd1bc Merge pull request #4729 from BookStackApp/description_wysiwyg
Simple WYSIWYG for description fields and comments
2023-12-22 15:28:13 +00:00
Dan Brown
3668949705 Input WYSIWYG: Fixed up some dark mode elements 2023-12-22 15:16:06 +00:00
Dan Brown
7cd0629a75 Input WYSIWYG: Updated exports to handle HTML descriptions 2023-12-22 14:57:20 +00:00
Dan Brown
fb3cfaf7c7 Input WYSIWYG: Updated API examples to align with changes 2023-12-22 14:37:48 +00:00
Dan Brown
2a7a81e749 Input WYSIWYG: Updated API testing, fixed description set issue
Fixed issue where an existing description_html field would not be
updated via 'description' input.
2023-12-22 13:17:23 +00:00
Dan Brown
00ae04e0bd Input WYSIWYG: Updated API to show/accept html descriptions
Also aligned books, shelves and chapters to return description content
and some relations (where not breaking API) in create/update responses
also so that information can be seen direct from that input in a
request.

API docs and tests not yet updated to match.
2023-12-21 13:23:52 +00:00
Dan Brown
ed5d67e609 Input WYSIWYG: Aligned newline handling with old descriptions
To ensure consistenent behaviour before/after changes.
Added tests to cover.
2023-12-20 17:40:58 +00:00
Dan Brown
a21ca44633 Input WYSIWYG: Fixed existing tests, fixed empty description handling 2023-12-20 17:21:09 +00:00
Dan Brown
7fd6d5b2cc Input WYSIWYG: Updated tests, Added simple html limiting 2023-12-19 15:10:29 +00:00
Dan Brown
077b9709d4 Input WYSIWYG: Added testing for description references 2023-12-19 12:55:51 +00:00
Dan Brown
2fbed3919b Input WYSIWYG: Added dynamic options for entity selector popups
So that multiple elements on the page can share the same popup, with
different search options.
2023-12-19 12:09:57 +00:00
Dan Brown
c07aa056c2 Input WYSIWYG: Updated UpdateUrlCommand, Added chapter HTML display 2023-12-18 18:31:16 +00:00
Dan Brown
bc354e8b12 Input WYSIWYG: Updated reference link updating for descriptions 2023-12-18 18:12:36 +00:00
Dan Brown
307fae39c4 Input WYSIWYG: Added reference store & fetch handling
For book, shelves and chapters.
Made much of the existing handling generic to entity types.
Added new MixedEntityListLoader to help load lists somewhat efficiently.
Only manually tested so far.
2023-12-18 16:23:40 +00:00
Dan Brown
c622b785a9 Input WYSIWYG: Added description_html field, added store logic
Rolled out HTML editor field and store logic across all target entity
types. Cleaned up WYSIWYG input logic and design.
Cleaned up some injected classes while there.
2023-12-17 15:02:15 +00:00
Dan Brown
569542f0bb Input WYSIWYG: Added compontent and rough logic to book form
Just as a draft for prototyping and playing around to get things
started.
2023-12-16 14:48:35 +00:00
Dan Brown
fc2e8ed315 Merge pull request #4728 from BookStackApp/friendlier_buttons
Design: Updated buttons to be a bit friendlier
2023-12-16 14:04:57 +00:00
Dan Brown
0c4dd7874c Design: Updated buttons to be a bit friendlier
Old all-caps button design made them a bit angry, and kinda odd and
outdated. This updates them to use their original source text casing
(which may help for translation variations) while being a bit rounder
with a better defined shadow for outline buttons.
2023-12-16 14:03:12 +00:00
Dan Brown
7250671889 Merge pull request #4727 from BookStackApp/editor_video_alignment
WYSWIYG: Allowed video/embed alignment controls
2023-12-16 12:32:52 +00:00
Dan Brown
5395ca2f00 WYSWIYG: Allowed video/embed alignment controls
Required a lot of working around TinyMCE since it added a
preview/wrapper element in the editor which complicates things.
Added view new "fixes.js" file so large hacks to default TinyMCe
functionality are kept in one place.
2023-12-16 12:22:40 +00:00
Luke T. Shumaker
c76d12d1de Oidc: Properly query the UserInfo Endpoint
BooksStack's OIDC Client requests the 'profile' and 'email' scope values
in order to have access to the 'name', 'email', and other claims.  It
looks for these claims in the ID Token that is returned along with the
Access Token.

However, the OIDC-core specification section 5.4 [1] only requires that
the Provider include those claims in the ID Token *if* an Access Token is
not also issued.  If an Access Token is issued, the Provider can leave out
those claims from the ID Token, and the Client is supposed to obtain them
by submitting the Access Token to the UserInfo Endpoint.

So I suppose it's just good luck that the OIDC Providers that BookStack
has been tested with just so happen to also stick those claims in the ID
Token even though they don't have to.  But others (in particular:
https://login.infomaniak.com) don't do so, and require fetching the
UserInfo Endpoint.)

A workaround is currently possible by having the user write a theme with a
ThemeEvents::OIDC_ID_TOKEN_PRE_VALIDATE hook that fetches the UserInfo
Endpoint.  This workaround isn't great, for a few reasons:
 1. Asking the user to implement core parts of the OIDC protocol is silly.
 2. The user either needs to re-fetch the .well-known/openid-configuration
    file to discover the endpoint (adding yet another round-trip to each
    login) or hard-code the endpoint, which is fragile.
 3. The hook doesn't receive the HTTP client configuration.

So, have BookStack's OidcService fetch the UserInfo Endpoint and inject
those claims into the ID Token, if a UserInfo Endpoint is defined.
Two points about this:
 - Injecting them into the ID Token's claims is the most obvious approach
   given the current code structure; though I'm not sure it is the best
   approach, perhaps it should instead fetch the user info in
   processAuthorizationResponse() and pass that as an argument to
   processAccessTokenCallback() which would then need a bit of
   restructuring.  But this made sense because it's also how the
   ThemeEvents::OIDC_ID_TOKEN_PRE_VALIDATE hook works.
 - OIDC *requires* that a UserInfo Endpoint exists, so why bother with
   that "if a UserInfo Endpoint is defined" bit?  Simply out of an
   abundance of caution that there's an existing BookStack user that is
   relying on it not fetching the UserInfo Endpoint in order to work with
   a non-compliant OIDC Provider.

[1]: https://openid.net/specs/openid-connect-core-1_0.html#ScopeClaims
2023-12-15 14:11:48 -07:00
Dan Brown
56d07f1909 Users API: Fixed sending invite when using form requests
- Cast send_invite value in cases where it might not have been a boolean,
  which occurs on non-JSON requests.
- Added test to cover.
- Updated API docs to mention and shown boolean usage.
2023-12-13 15:13:54 +00:00
Dan Brown
4896c4047f Merge pull request #4721 from BookStackApp/default-templates
Continued: Default book templates
2023-12-12 16:06:35 +00:00
Dan Brown
3af07addf6 Default templates: Fixed syntax for php8.0, added test
Null accessor is akward in php8.0 and throws warnings, so removed.
Added test to check template assingment handling on page delete.
2023-12-12 15:59:12 +00:00
Dan Brown
2f3806244c Default templates: Added permission checks to selector test 2023-12-12 15:41:56 +00:00
Dan Brown
2081a783f3 Default templates: Cleaned up ux, added case for added endpoint
Cleaned up and updated page picker a bit, allowing longer names to show,
clicking through to item without triggering popup, and updated to use
hidden attributes instead of styles.

Added phpunit tests to cover supporting entity-selector-templates
endpoint.
2023-12-12 15:38:09 +00:00
Dan Brown
d75eb06777 Default templates: Added tests to cover functionality
Included new helper in Test PermissionProvider to set app to public,
since that's a common test scenario.
2023-12-12 15:04:40 +00:00
Dan Brown
4017048555 Page Templates: Changed template field name, added API support 2023-12-12 12:14:00 +00:00
Dan Brown
7ebe7d4e58 Default templates: Added page picker and working forms
- Adapted existing page picker to be usable elsewhere.
- Added endpoint for getting templates for entity picker.
- Added search template filter to support above.
- Updated book save handling to check/validate submitted template.
  - Allows non-visible pages to flow through the save process, if not
    being changed.
- Updated page deletes to handle removal of default usage on books.
- Tweaked wording and form styles to suit.
- Updated migration to explicity reflect default value.
2023-12-11 15:58:27 +00:00
Dan Brown
d61f42a377 Default Templates: Started review and updates from PR code 2023-12-11 12:33:20 +00:00
Dan Brown
968bc8cdf3 Merge branch 'development' into default-templates 2023-12-11 11:41:43 +00:00
Dan Brown
c13fd2a9e6 PHPStan: Fixed larastan loading and address some level2 issues 2023-12-10 14:58:05 +00:00
Dan Brown
45ce7a7126 URL Handling: Removed referrer-based redirect handling
Swapped back handling to instead be pre-determined instead of being
based upon session/referrer which would cause inconsistent results when
referrer data was not available (redirect to app-loaded images/files).

To support, this adds a mechansism to provide a URL through request
data.

Also cleaned up some imports in code while making changes.
Closes #4656.
2023-12-10 12:37:21 +00:00
Dan Brown
11955e270c Depenencies: Updated NPM packages
Avoided updating markdown-it package to 14 for now since it would cause
bundle size to inflate. Don't think ESBuild is properly tree shaking
"entities" sub package which inflates size.
2023-12-09 10:49:28 +00:00
Dan Brown
33374524bf Dependencies: Updated composer PHP deps 2023-12-09 10:05:23 +00:00
Dan Brown
8cbaa3e27c SAML2: Fixed non-spec point of logout, Improved redirect location
This changes the point-of-logout to be within the initial part of the
SAML logout flow, as per 5.3.2 of the SAML spec, processing step 2.
This also improves the logout redirect handling to use the global
redirect suggestion so that auto-login handling is properly taken into
account.

Added tests to cover.
Manual testing performed against keycloak.
For #4713
2023-12-08 18:42:13 +00:00
Dan Brown
4c0b7f3123 Merge pull request #4714 from BookStackApp/oidc_logout
OIDC RP-Initiated logout
2023-12-07 18:00:32 +00:00
Dan Brown
7312300d53 OIDC: Update example env option to reflect correct default 2023-12-07 17:59:48 +00:00
Dan Brown
81d256aebd OIDC RP Logout: Fixed issues during testing
- Disabled by default due to strict rejection by auth systems.
- Fixed issue when autoloading logout URL, but not provided in
  autodiscovery response.
- Added proper handling for if the logout URL contains a query string
  already.
- Added extra tests to cover.
- Forced config endpoint to be used, if set as a string, instead of
  autodiscovery endpoint.
2023-12-07 17:45:17 +00:00
Dan Brown
a72e0fee70 Tests: Fixed debug test to work with social class changes 2023-12-06 16:57:15 +00:00
Dan Brown
f32cfb4292 OIDC RP Logout: Added autodiscovery support and test cases 2023-12-06 16:41:50 +00:00
Dan Brown
bba7dcce49 Auth: Refactored OIDC RP-logout PR code, Extracted logout
Extracted logout to the login service so the logic can be shared instead
of re-implemented at each stage. For this, the SocialAuthService was
split so the driver management is in its own class, so it can be used
elsewhere without use (or circular dependencies) of the
SocialAuthService.

During review of #4467
2023-12-06 13:49:53 +00:00
Dan Brown
cc10d1ddfc Merge branch 'fix/oidc-logout' into development 2023-12-06 12:14:43 +00:00
Dan Brown
0254527bd9 RTL: Made a range of fixes & improvments for RTL text
- Updated HTML exports to have auto direction to properly react to RTL
  text when in the content.
- Fixed RTL spacing issues in new editor design changes.
- Fixed pointer arrow being angled wrong on RTL languages.

Related to #4645
2023-12-05 18:53:48 +00:00
Dan Brown
11853361b0 SAML2: Included parsed groups in dump data
Updated code style of class while there.
Removed redundant check and string translation used.

For #4706
2023-12-03 19:36:03 +00:00
Dan Brown
596f7314cd Merge branch 'v23-10' into development 2023-12-03 18:57:07 +00:00
Dan Brown
1011d61713 Merge pull request #4688 from BookStackApp/include-parser
New include tag parser
2023-11-27 21:54:18 +00:00
Dan Brown
652d5417bf Includes: Added back support for parse theme event
Managed to do this in an API-compatible way although resuling output may
differ due to new dom handling in general, although user content is used
inline to remain as comptable as possible.
2023-11-27 21:39:43 +00:00
Dan Brown
b569827114 Includes: Added ID de-duplicating and more thorough clean-up 2023-11-27 20:16:27 +00:00
Dan Brown
71c93c8878 Includes: Switched page to new system
- Added mulit-level depth parsing.
- Updating usage of HTML doc in page content to be efficient.
- Removed now redundant PageContentTest cases.
- Made some include system fixes based upon testing.
2023-11-27 19:54:47 +00:00
Dan Brown
4874dc1304 Includes: Updated logic regarding parent block els, added tests
Expanded tests with many more cases, and added fixes for failed
scenarios.
Updated logic to specifically handling parent <p> tags, and now assume
compatibility with parent block types elswhere to allow use in a
variety of scenarios (td, details, blockquote etc...).
2023-11-25 17:32:00 +00:00
Dan Brown
c88eb729a4 Includes: Added block-level handling to new include system
Implements block promoting to body (including position choosing based
upon likely tag position within parent) and block splitting where we're
only a single depth down from the body child.
2023-11-24 23:39:16 +00:00
Dan Brown
75936454cc Includes: Developed to get new system working with inline includes
Adds logic for locating and splitting text nodes.
Adds specific classes to offload tag/content specific logic.
2023-11-23 14:29:07 +00:00
Dan Brown
04d21c8a97 Includes: Started foundations for new include tag parser 2023-11-22 22:14:28 +00:00
Dan Brown
5d08f7cf14 Updated version and assets for release v23.10.4 2023-11-20 14:19:46 +00:00
Dan Brown
8744eb2d62 Merge branch 'v23-10' into release 2023-11-20 14:02:23 +00:00
Dan Brown
15d7161428 Images: Prevented base64 extraction without permission
Also added content sniffing as an extra check.
Added tests to cover.
2023-11-20 13:32:31 +00:00
Dan Brown
9b1f820596 Images: Forced intervention loading via specific method
Updated image loading for intervention library to be via a specific
'initFromBinary' method to avoid being overly accepting of input types
and mechansisms.

For CVE-2023-6199
2023-11-19 16:34:29 +00:00
Dan Brown
2fb873f7ef Favicon: Moved resizing to specific resizer class 2023-11-19 15:57:19 +00:00
Dan Brown
22a9cf1e48 LogicalTheme: Added events for registering web routes
Added to allow easier registration of routes.
Added for normal web and authed routes.
Included testing to cover.
2023-11-17 13:45:57 +00:00
Dan Brown
37a17e858a HTML: Tweaked output from full HtmlDocument
Saves specifically the document element on output to HTML, since this
results in just the outer HTML being saved while not including the extra
XML tags which would show up before with the changes to force utf8
usage.
2023-11-14 17:23:05 +00:00
Dan Brown
eab9c1081e Merge pull request #4673 from BookStackApp/html_doc_alignment
HTML: Aligned and standardised DOMDocument usage
2023-11-14 17:22:30 +00:00
Dan Brown
db7b11fe93 HTML: Aligned and standardised DOMDocument usage
Adds a thin wrapper for DOMDocument to simplify and align usage within
all areas of BookStack.
Also means we move away from old depreacted mb_convert_encoding usage.

Closes #4638
2023-11-14 15:46:32 +00:00
Dan Brown
3a6f50e668 Merge pull request #4661 from BookStackApp/tinymce_update
WYSIWYG: Updated TinyMCE from 6.5.1 to 6.7.2
2023-11-14 13:15:32 +00:00
Dan Brown
76417efd6f Merge branch 'Man-in-Black-patch-1' into development 2023-11-14 10:40:30 +00:00
Dan Brown
d41fd7a8dd Notifications: Review of PR to include path path #4629
- Merged book and chapter name items to a single page path list item
  which has links to parent page/chapter.
- Added permission filtering to page path elements.
- Added page path to also be on comment notifications.
- Updated testing to cover.
- Added new Message Line objects to support.

Done during review of #4629
2023-11-14 10:38:34 +00:00
Sascha
65ac197be4 Added book name to the mail template
added book name

synced with actual file from dev branch

added book name

add book name

added book name

extended with chaptername

extended with chapter name

Update PageUpdateNotification.php

Update notifications.php

Update notifications.php

Update notifications.php

correction of chapter syntax

correction of chapter syntax
2023-11-14 10:38:34 +00:00
Dan Brown
bff1f502bb JS: Removed random extra import 2023-11-09 13:36:00 +00:00
Dan Brown
f8ebbb7553 WYSIWYG: Updated TinyMCE from 6.5.1 to 6.7.2 2023-11-09 13:34:00 +00:00
Dan Brown
d8383cfa80 Updated version and assets for release v23.10.2 2023-11-07 15:22:34 +00:00
Dan Brown
4626278447 Merge branch 'development' into release 2023-11-07 15:22:11 +00:00
Dan Brown
48f115291a Updated translator attribution before release v23.10.2 2023-11-07 15:12:15 +00:00
Dan Brown
6cd38a8ace Merge branch 'development' of github.com:BookStackApp/BookStack into development 2023-11-07 15:09:54 +00:00
Dan Brown
fa6ac211b6 Dropdowns: Fixed bad direction logic, added dynmaic height
Changes since adding notifications would cause direction to be assessed
upon max height of 80vh, which caused large dropdowns like the audit log
dropdown to drop up and/or go offscreen.
This restores the default assessment of 500px, and adds dynamic
max-height adjustment to provide more room for large dropdowns.

For #4652
2023-11-07 15:07:11 +00:00
Dan Brown
1310db19ca Updated translations with latest Crowdin changes (#4643) 2023-11-07 14:40:53 +00:00
Dan Brown
ea0469e61a PWA: Prevent passing credentials to avoid redirection issues
For #4649
More of a patch around the issue for now.
Have opened #4656 to properly address.
2023-11-07 14:33:37 +00:00
Dan Brown
c61af9c22b Updated version and assets for release v23.10.1 2023-11-02 14:44:53 +00:00
Dan Brown
72521d0906 Merge branch 'development' into release 2023-11-02 14:35:49 +00:00
Dan Brown
889b0dae3b Updated translations with latest Crowdin changes (#4631) 2023-11-02 14:30:34 +00:00
Dan Brown
48bda115aa Langs: Enabled Nynorsk option, updated translator attribution 2023-11-02 14:17:56 +00:00
Dan Brown
9dd05b8751 MD Editor: Fixed lack of toolbar BG when in fullscreen
For #4641
2023-11-02 12:41:07 +00:00
Dan Brown
02d140120a Editor toolbox: Updated tabs to use link color
Change due to link color being more suitable in this case since it's not
specifically a block with light text which is what app color is suited
for.
Specifically better for dark mode when a dark app color is used.

For #4630
2023-11-02 12:34:57 +00:00
Dan Brown
38ac3c959b Page JS: Improved block jumping and highlighting
- Updated anchor scroll change to open up details blocks if the target
  exists within.
- Updated highlighting and animation implementation to fix hardly visible highlighting.
- Removed old, now unused, handing of CM instances in details blocks.

Related to #4637.
2023-11-01 18:49:47 +00:00
Dan Brown
324e403ae5 JS Events: Added CM pre/post init events
To allow hacking of all CodeMirror instances.
Closes #4639.
2023-11-01 17:56:52 +00:00
Dan Brown
fce7190257 Testing: Added PHP8.3 support
Also fixed text which could through deprecation notice due to not having
a properly formed comment in use.
For #4633
2023-10-31 15:52:01 +00:00
Dan Brown
c640db8434 Readme: Updated sponsorship links and language contribution info
- Updated sponsor text since it only mentioned GitHub, nothing else.
- Updated translation contribution info to dissuade code-based
  contributions due to issues with conflicts/sync.
2023-10-30 17:13:39 +00:00
Dan Brown
7e44b195c5 Updated version and assets for release v23.10 2023-10-30 12:15:59 +00:00
Dan Brown
5b45eac5e1 Merge branch 'development' into release 2023-10-30 12:14:23 +00:00
Dan Brown
49b286cd34 Demo mode: Updated my account access to be more selective 2023-10-30 12:07:18 +00:00
Dan Brown
e006f9674f Langs: Updated translators and locale list pre v23.10 2023-10-30 11:41:36 +00:00
Dan Brown
8bffcebd64 Updated translations with latest Crowdin changes (#4523) 2023-10-30 11:16:19 +00:00
Dan Brown
7c4dc981cd Middlware: Prevented caching of all app requests
Previously we'd prevent caching of authed responses for security
(prevent back cache or proxy caching) but caching could still be an
issue in non-auth scenarios due to CSRF (eg. returning to login screen after
session expiry).

For #4600
2023-10-23 13:32:15 +01:00
Dan Brown
9b4f1fb981 Styles: Aligned empty state alignment & consistency
- Fixed inital empty state margins/paddings to be aligned and not differ
when lists are empty.
- Aligned button/action display when viewing empty entities.
- Fixed use of non-existing permission in books for book empty state
  button.

Fixes #4563
2023-10-23 11:53:19 +01:00
Dan Brown
d42af4affc Shortcuts: Prevented help shown when in inputs
For #4606
2023-10-23 11:04:09 +01:00
Dan Brown
8375d341ea Deps: Updated npm and composer packages 2023-10-20 16:39:40 +01:00
Dan Brown
f5756ff28a Security: Swapped twitter for mastodon link 2023-10-19 16:53:02 +01:00
Dan Brown
c513cdaebe Merge pull request #4618 from radiantwave/patch-1
Remove huntr from SECURITY.md
2023-10-19 16:50:30 +01:00
Dan Brown
995b7d61e9 Merge pull request #4615 from BookStackApp/user_account
User preferences/options cleanup
2023-10-19 16:49:06 +01:00
Dan Brown
02bfaffeb4 My Acount: Updated old preference url reference for watches 2023-10-19 16:37:55 +01:00
Daniel
38fe40809b Update SECURITY.md
Remove huntr
2023-10-19 17:12:18 +02:00
Dan Brown
ce53f641ad My Account: Covered profile and auth pages with tests 2023-10-19 16:06:59 +01:00
Dan Brown
f55e7ca3c9 User Account: Ensured page titles for pages and api tokens 2023-10-19 15:24:48 +01:00
Dan Brown
fabc854390 My Account: Updated and started adding to tests
- Updated existing tests now affected by my-account changes.
- Updated some existing tests to more accuractly check the scenario.
- Updated some code styling in SocialController.
- Fixed redirects for social account flows to fit my-account.
- Added test for social account attaching.
- Added test for api token redirect handling.
2023-10-19 14:18:42 +01:00
Dan Brown
12946414b0 API Tokens: Updated interfaces to return to correct location
Since management of API tokens can be accessed via two routes, this adds
tracking and handling to reutrn the user to the correct place.
2023-10-19 11:31:45 +01:00
Dan Brown
f9422dff18 My Account: Added self-delete flow 2023-10-19 10:48:27 +01:00
Dan Brown
cf72e48d2a User form: Always show external auth field, update access control
Updated old user management routes to only be accessible with permission
to manage users, so also removed old content controls checking for that
permission.
2023-10-19 10:20:04 +01:00
Dan Brown
e4ea73ee25 My Account: Cleaned-up/reorganised user header dropdown 2023-10-18 17:57:14 +01:00
Dan Brown
03c44b3992 My Account: Extracted/tweaked profile text, removed old index 2023-10-18 17:53:58 +01:00
Dan Brown
c1b01639c1 My Account: Built out profile page & endpoints
Text currently hard-coded, needs finalising and extracting.
2023-10-18 12:39:57 +01:00
Dan Brown
a868012048 Users: Built out auth page for my-account section 2023-10-17 17:38:07 +01:00
Dan Brown
a9d0f36766 User: Started cleanup of user self-management
- Moved preference views to more general "my-account" area.
- Started new layout for my-account with sidebar.
- Added MFA to prefeences view (to be moved).
2023-10-17 13:11:10 +01:00
Dan Brown
3274181e14 Merge pull request #4604 from BookStackApp/editor_trim_enhancement
Editor design update
2023-10-14 17:30:04 +01:00
Dan Brown
8166e27f2b Editors: Properly aligned edit area border radius 2023-10-14 17:18:09 +01:00
Dan Brown
8ffa436f3d Editors: Adjusted new design for mobile and dark mode
Tested new design across FF, Chrome, and Gnome web (webkit)
2023-10-14 17:10:29 +01:00
Dan Brown
8c10959339 Editors: Tightened up new design, adjusted for MD editor 2023-10-14 16:33:48 +01:00
Dan Brown
45c7409092 Editor: Started toying with more singificant design update 2023-10-13 17:33:11 +01:00
Dan Brown
a12b60e1ad Editor: Started attempts to improve design elements 2023-10-08 15:04:07 +01:00
Dan Brown
ccb3c2516a Homepage: Made much nicer at ipad-like widths
Updated default homepage layout to be much nicer at ipad-like widths by
switching to css-column approach at those breakpoints.
Also neated top actions by switching to simpler flexbox layout.

Fixes #4596
2023-10-07 12:38:54 +01:00
Dan Brown
2e2272343b Merge branch 'LawssssCat/development' into development 2023-10-06 12:03:38 +01:00
Dan Brown
031067745b Layout: Restructured tri-layout for sidebar control
Restructured tri-layout grid system, so the sidebars are contained in
their own child grid system, mimicking the parent grid, so we can treat
them as part of the same parent scroll container at smaller screen
sizes for consistent scroll/sticky behavior.

Tested on Firefox, Chromium, Gnome Web and Safari (MacOS).

For #4394
Changes made during review of #4562
2023-10-06 12:03:38 +01:00
Dan Brown
1267068d9c CI: Added path filtering to actions
In the hope we can make the CI runs a bit more efficient and energy
conscious, by only running when relevant files have changed.
2023-10-04 09:18:24 +01:00
Dan Brown
0241032f06 Tags: Fixed enter press clearing field
For #4570
2023-10-04 09:08:10 +01:00
Dan Brown
bd7c7eb8d6 Print Styles: Removed use of seperate style sheet
Seemed a bit redundant and complicated, since we're only adding a few
extra styles. Just merged into main styles instead.
2023-10-03 15:14:21 +01:00
Dan Brown
c5d5b6e3c1 Print Styles: Fixed header/footer content showing
Extra bits were showing due to recent changes.
Done a quick pass through major display views.

Fixes #4594
2023-10-03 14:59:35 +01:00
Dan Brown
1005f4bd7a Testing: Added favicon cleanup
Was leaving a changed favicon leaving other test to fail.
2023-10-03 14:50:54 +01:00
Dan Brown
b24296e0c9 Added NETWAYS to readme sponsor list
Related to:
edceda5342
2023-10-03 12:10:45 +01:00
Dan Brown
d1f28ed245 Merge branch 'basic-pwa-support' into development 2023-10-02 15:58:07 +01:00
Dan Brown
1d91b4d8a6 PWA Manifest: Tweaks during review of PR #4430
- Updated to go through HomeController with the builder as a helper
  class.
- Extracted some reapeated items into variables in manifest.
- Updated background color to match those used by BookStack.
- Removed reference of icon.ico since its not intended to be used.
- Added tests to cover functionality.

Review of #4430
2023-10-02 15:54:39 +01:00
Dan Brown
8bba5dd5a0 Merge pull request #4578 from BookStackApp/upload_handling
Improvements to file/image upload handling UX
2023-10-01 17:20:10 +00:00
Dan Brown
ffb04a8be6 JS: Fixed ESLint issues 2023-10-01 18:13:54 +01:00
Dan Brown
b2d48d9a7f Images: Rolled out image memory handling to image actions
- Moved thumnbail loading out of repo into ImageResizer.
- Updated gallery and editor image handling to show errors where
  possible to indicate memory issues for resizing/thumbs.
- Updated gallery to load image data in a per-image basis via edit form
  for more resiliant thumb/data fetching. Data was previously provided
  via gallery listing, which could be affected by failing generation
  of other images.
- Updated image manager double click handling to be more pleasant and
  not flash away the edit form.
- Updated editor handlers to use main URL when thumbs fail to load.
2023-10-01 13:05:18 +01:00
Dan Brown
20bcbd76ef Images: Extracted out image resizing to its own class 2023-09-30 20:00:48 +01:00
Dan Brown
e703009d7f Images: Added thin wrapper around image filesystem instances
Extracts duplicated required handling (Like path adjustment) out to
simpler storage disk instance which can be passed around.
2023-09-30 19:12:22 +01:00
Dan Brown
7247e31936 Images: Started refactor of image service
To break it up.
Also added better memory handling to other parts of the app.
2023-09-30 18:28:42 +01:00
Dan Brown
40721433f7 Image manager: Tweaked grid sizing to prevent massive items 2023-09-30 12:43:51 +01:00
Dan Brown
97274a8140 Images: Added test to cover thubmnail regen endpoint 2023-09-30 12:29:49 +01:00
Dan Brown
5c318a45b8 Images: Reverted some thumbnails to be on-demand generated
Added since we can't always be sure of future image usage, and in many
cases we don't generate ahead-of-time.
Also:
- Simplified image handling on certain models.
- Updated various string handling operations to use newer functions.
2023-09-30 12:09:29 +01:00
Dan Brown
5af3041b9b Thumbnails: Added OOM handling and regen endpoint
- Added some level of app out-of-memory handling so we can show a proper
  error message upon OOM events.
- Added endpoint and image-manager button/action for regenerating
  thumbnails for an image so they can be re-created upon failure.
2023-09-29 13:54:08 +01:00
Dan Brown
cc0827ff28 Images: Updated to create thumbnails at specific events 2023-09-29 11:46:32 +01:00
Dan Brown
59da7666b5 Uploads: Added user-facing message for Laravel post limit handling
Uploads over the post max size Would previously error without a
clean user facing message. This catches that error to provide a
user friendly message, compatible with our common error handling.

Tested on image manager handling.
Added test to cover.
2023-09-25 13:48:23 +01:00
JonatanRek
287ed4ff3b Remove Dumps 2023-09-24 20:19:53 +02:00
Dan Brown
21badde4ef Editors: Updated entity link select to pre-fill with selection
Updated all uses across both editors, so the entity link selector popup
now initates a search with the selection text if existing.

For #4571
2023-09-24 18:33:33 +01:00
Dan Brown
e9664dc678 Exports: Fixed issues with book text export format
- Fixed missing page content for direct page children
- Fixed lack of book description.
- Fixed inconsistent spacing between items.
- Fixed lack of spacing between HTML items when HTML on same line.

For #4557
2023-09-24 18:03:37 +01:00
Dan Brown
d5a3bdb7aa Header: Simplified, split and re-orgranised view file(s)
- Moved "common" template partials, that are only used in layouts, to
  layouts/parts folder.
- Simplified HTML structure of header template.
- Extracted logo and links from header template to simplify.
- Added header-links-start template for easier extension/customization
  without needing to override full list of links.
  - Added test to cover usage of this.

For #4564
2023-09-24 10:29:51 +01:00
Dan Brown
c3b4128a38 Homepage: Added tags button to non-default home views
For #4558
2023-09-24 09:31:44 +01:00
Dan Brown
f77bb01b51 Search: Added further backslash handling
Added due to now not being able to perform an exact search where
contains a trailing backslash.
Now all backslashes in exact terms are consided escape chars
and require escaping themselves.
Potential breaking change due to search syntax handling change.

Related to #4535.
2023-09-23 13:41:10 +01:00
Dan Brown
fb417828a4 Readme: Updated badges, sponsors and top links 2023-09-23 12:47:24 +01:00
JonatanRek
57791c1466 Fix Reloading changes on dark mode switch 2023-09-22 11:31:24 +02:00
JonatanRek
46e3b2ceb3 Merge branch 'basic-pwa-support' of https://github.com/GamerClassN7/BookStack into basic-pwa-support 2023-09-22 11:19:38 +02:00
JonatanRek
10e8e1a88d New line fix 2023-09-22 11:19:34 +02:00
JonatanRek
7e09c9a147 Update HomeController.php 2023-09-22 11:19:17 +02:00
JonatanRek
2a2f893fcc Formating Fixes 2023-09-22 11:18:10 +02:00
JonatanRek
9b99664bff Additional Tweaks and FIxes 2023-09-22 11:15:13 +02:00
JonatanRek
f910424fa3 Implementation of required changes 2023-09-22 11:00:41 +02:00
JonatanRek
6e19a8a4bb Merge branch 'basic-pwa-support' of https://github.com/GamerClassN7/BookStack into basic-pwa-support 2023-09-22 10:49:53 +02:00
JonatanRek
cb9c3fc9f5 Fix Dark theme 2023-09-22 10:49:37 +02:00
JonatanRek
effc03e99e Merge branch 'BookStackApp:development' into basic-pwa-support 2023-09-22 10:48:48 +02:00
Dan Brown
8964575973 Search: Added support for escaped exact terms
Also prevented use of empty exact matches.
Prevents issues when attempting to use exact search terms in inputs for
just search terms, and use of single " chars within search terms since
these would get auto-promoted to exacts.

For #4535
2023-09-19 20:09:33 +01:00
Dan Brown
4b4d8ba2a1 Avatar Commend: Simplified and updated during review
During review of #4560.

- Simplified command to share as much log as possible across different
  run options.
- Extracted out user handling to share with MFA command.
- Added specific handling for disabled avatar fetching.
- Added mention of avatar endpoint, to make it clear where these avatars
  are coming from (Protect against user expectation of LDAP avatar sync).
- Simplified a range of the testing.
- Tweaked wording and code formatting.
2023-09-19 15:53:01 +01:00
lawsssscat
588ed785d2 fix Sidebar scrolling at mid-range sceen 2023-09-19 22:12:33 +08:00
Marc Hagen
ca98155373 fix: Actually check if we have correct data 2023-09-18 20:04:59 +02:00
Marc Hagen
ea7592509f feat: Artisan command for updating avatars for existing users 2023-09-18 20:04:28 +02:00
Dan Brown
95b9ea1a21 Dev: Reviewed and expanded on PHP testing docs 2023-09-17 23:41:02 +01:00
Dan Brown
684a9dee8e Merge branch 'tusharnain4578/development' into development 2023-09-17 22:29:06 +01:00
Dan Brown
c42cd29ed3 Notifications: Updated comment notif. prefs. test
Combined testcases, updated to use actual text strings, and set comments
setting via correct method.

Made during review of #4552
2023-09-17 22:26:51 +01:00
Dan Brown
35813e818d Merge pull request #4555 from BookStackApp/language_cleanup
Language cleanup
2023-09-17 22:15:38 +01:00
Dan Brown
78bf11cf65 Locales: Removed a lot of existing locale handling
There was a lot of locale handling to get correct/expected date
formatting within the app.
Carbon now has built-in locale content rather than us needing to target
specific system locales.

This also removes setting locale via Carbon directly.
Carbon registers its own Laravel service provider which seems to
accurately pull the correct locale from the app.

For #4555
2023-09-17 22:02:12 +01:00
Tushar Nain
baa957d980 Update UserPreferencesTest.php
Added Testcases for preferences menu of Comment Notifications visibility when comments are enabled/disabled.
2023-09-17 23:31:01 +05:30
Dan Brown
b42e8cdb63 Locales: Fixed errors occuring for PHP < 8.2 2023-09-17 17:35:00 +01:00
Dan Brown
8994c1b9d9 Locales: More use of locale objects, Addressed failing tests 2023-09-17 16:20:21 +01:00
Dan Brown
ac9a65945f Locales: Performed cleanup and alignment of locale handling
- Reduced app settings down to what's required.
- Used new view-shared $locale object instead of using globals via
  config.
- Aligned language used to default on "locale" instead of mixing
  locale/language.

For #4501
2023-09-17 13:31:38 +01:00
Dan Brown
b292cf7090 Extracted icon helper, aligned container resolution
Also updated breadcrumb view composer to current standards.
Closes #4553
2023-09-16 18:26:28 +01:00
Dan Brown
54791c8627 Merge pull request #4554 from BookStackApp/guest_user_cleanup
Guest control: Cleaned methods involved in fetching/handling
2023-09-16 13:59:16 +01:00
Dan Brown
e16bdf443c Removed redundant null check 2023-09-16 13:49:03 +01:00
Dan Brown
b90033a730 Guest control: Cleaned methods involved in fetching/handling
- Moves guest user caching from User class to app container for
  simplicity.
- Updates test to use simpler $this->users->guest() method for
  consistency.
- Streamlined helpers to avoid function overlap for simplicity.
- Extracted user profile dropdown while doing changes.
2023-09-16 13:18:35 +01:00
Dan Brown
9ac932fc28 Merge branch 'v23-08' into development 2023-09-16 11:55:57 +01:00
Tushar Nain
6a5361d853 Fixed : Comment notification settings are visible even if comments are disabled
Added a UX condition to display comment notification settings, only if the user has enabled the comment notifications.
2023-09-16 14:00:08 +05:30
Dan Brown
c1d30341e7 Updated version and assets for release v23.08.3 2023-09-15 13:49:40 +01:00
Dan Brown
80d2b4913b Merge branch 'v23-08' into release 2023-09-15 13:49:12 +01:00
Dan Brown
45b8d6cd0c Comments: Fixed wrong identification of parent comment
Would cause comment reply notifications to not be sent to expected user.
Updated test to cover problem case.

For #4548
2023-09-15 13:38:02 +01:00
Dan Brown
dfaf6f7c13 Cleanup Command: Allowed running non-interactively
For #4541
2023-09-14 14:17:20 +01:00
Dan Brown
417705651c Dark Mode: Fixed not toggle action when dark by default
Added test to cover.
For #4543.
2023-09-14 13:53:24 +01:00
Dan Brown
4ec600adfa Langs: Added Uzbek, Updated translator attribution
For #4527
2023-09-13 10:52:12 +01:00
Dan Brown
709c182bda Merge branch 'Bajszi97/development' into development 2023-09-13 10:12:49 +01:00
Dan Brown
a452092e40 Reviewed #4533, formatting and tweaks
- Updating formatting.
- Tweaked truncation to roughly match elipsis char to width used.
- Updated testing to use existing helpers, and ran check as admin user
  to avoid name conflicts.
2023-09-13 10:09:33 +01:00
Bajszi
83028f3fbe Test comment creator name truncation 2023-09-12 21:10:25 +02:00
Bajszi
f4deb13301 Truncate with three dots 2023-09-12 21:10:25 +02:00
Dan Brown
6e098905d4 Theme: Added handling for functions.php file load error
This adds specific handling for functions.php error loading to re-throw
errors wrapped in a more descriptive message, to make it clear the error
is due to an issue in their functions.php file.

Decided to throw and stop, rather than ignore & continue, to be on the
safe side in the event auth-level (or other security level) customizations
have been made via functions.php.

Adds test to cover.
Closes #4504
2023-09-12 12:34:02 +01:00
Bajszi
f997d3e0bb Trimmed name last resort 2023-09-11 21:27:15 +02:00
Dan Brown
8e3f8de627 Notifications: Reorgranised classes into domain specific folders
Closes #4500
2023-09-11 19:27:36 +01:00
Dan Brown
18f396c21b Views: Rolled out ID to similar recent activity lists
To allow for easier customization.
Related to #4530
2023-09-11 18:50:39 +01:00
Dan Brown
ec86576e1e Merge branch 'v23-08' into development 2023-09-11 18:43:23 +01:00
Dan Brown
99eb3e5f71 Comments: Fixed JS error when lacking commenting permissions
The page comments component would throw an error due to references to
form elements/content, when form elements may not exist due to
permisisons.

For #4531
2023-09-11 18:40:40 +01:00
Dan Brown
4985e39db4 Slack auth: Switched from community to laravel library
Tested locally before & after change, and looked at code to compare.
Nothing seen or experienced that should affect things, from testing all
is working as expected with no difference from before.
- Update composer requirement of socialite to that which included slack.
- Updated PHP depds while there.
- Updated format of socialite events to align with current documentation
  and to use class references instead of strings.
2023-09-11 15:26:04 +01:00
Dan Brown
05f2ec40cc OIDC: Moved name claim option handling from config to service
Closes #4494
2023-09-11 11:50:58 +01:00
Dan Brown
564dc70ac4 Fixed php8 compat issue, updated readme & templates
- Changed use of array spread since it was not supported in PHP8.0.
- Updated issue templates based to reduce less valueable fields, update
  some details, and try to help bug reports be more focused on bugs.
- Updated readme with peertube link and attribution advistory for
  translations PRs.
2023-09-11 11:37:07 +01:00
Dan Brown
2fbf5527c7 Simplified and aligned handling of mixed entity endpoints
Fixes #4444
2023-09-10 15:19:23 +01:00
Dan Brown
3928cbac18 Mail: changed default "MAIL_FROM" address
Used an "example.com" address so we're using a propoer reserved domain,
and to avoid these trying to be delivered to the main bookstackapp
domain.

Closes #4518
2023-09-09 12:41:37 +01:00
Dan Brown
8659ee0936 Merge pull request #4525 from BookStackApp/http_alignment
HTTP calling logic alignment
2023-09-08 17:30:44 +01:00
Dan Brown
06490f624c Removed use of HttpFetcher
- Fixed some existing issues in new aligned process.
- Manually tested each external call scenario.
2023-09-08 17:16:57 +01:00
Dan Brown
a8b5652210 Started aligning app-wide outbound http calling behaviour 2023-09-08 14:16:09 +01:00
Dan Brown
15da4b98ef Updated translations with latest Crowdin changes (#4512)
Last translation merge for possible continued v23.08 branch
2023-09-07 15:57:59 +01:00
Dan Brown
21cd2d17f6 Updated sponsors and dev version 2023-09-07 14:43:29 +01:00
Dan Brown
3f473528b1 Updated version and assets for release v23.08.2 2023-09-04 12:06:50 +01:00
Dan Brown
d0dcd4f61b Merge branch 'development' into release 2023-09-04 12:06:15 +01:00
Dan Brown
ad60517536 Updated translations with latest Crowdin changes (#4506) 2023-09-04 11:48:25 +01:00
Dan Brown
2c20abc872 WYSIWYG: Fixed filtering issue causing broken page edits
Could error upon div elements without classes, including drawings.

Related to #4510 and #4509
2023-09-04 11:25:05 +01:00
Dan Brown
bde66a1396 Updated version and assets for release v23.08.1 2023-09-03 17:40:19 +01:00
Dan Brown
4de5a2d9bf Merge branch 'development' into release 2023-09-03 17:39:56 +01:00
Dan Brown
2abbcf5c0f Updated translator attribution before release v23.08.1 2023-09-03 17:35:57 +01:00
Dan Brown
7a48516bf4 Updated translations with latest Crowdin changes (#4481) 2023-09-03 17:23:40 +01:00
Dan Brown
e31b50dabd Preferences: Fixed section screen flexibility
Improved wrapping and flex control to prevent button text force wrapping
to newlines.

For #4502
2023-09-03 16:58:29 +01:00
Dan Brown
817581aa0c Watching: Prevent issues when watchable or user is deleted
- Adds filtering to the watched items list in notification preferences
  so that deleted (recycle bin) items are removed via query.
- Adds relations and logic to properly remove watches upon user and
  entity delete events, to old watches in database do not linger.
- Adds testing to cover the above.

Did not add migration for existing data, since patch will be close to
introduction, and lingering DB entries don't open a security concern,
just some potential confusion in specific potential scenarios.
Probably not work extra migration risk, although could add in future if
concerns/issues are found.

Related to #4499
2023-09-03 14:19:43 +01:00
Dan Brown
1cd19c76ba Merge pull request #4497 from BookStackApp/notification_language
Notifications: User language for notification text
2023-09-02 15:47:26 +01:00
Dan Brown
5d38ae3c97 Merge pull request #4484 from omahs/patch-1
Fix typos
2023-09-02 15:44:01 +01:00
Dan Brown
a720b3725d Testing: Added entity decode flag and phpunit env option
- Passed decode flags to provide consistent behaviour across PHP
  versions during testing.
- Added env option to prevent local option taking action in PHPunit
  tests.
2023-09-02 15:39:45 +01:00
Dan Brown
3847a76134 Notifications: Aligned how user language is used
- This ensures content notifications are not translated to receiver
  language.
- This adds actual plaintext support for content notifications (Was
  previously just HTML as text view).
- Shares same base class across all mail notifications.
- Also cleaned up existing notification classes.

Future cleanup requested via #4501
2023-09-02 15:11:42 +01:00
Dan Brown
f91049a3f2 Notifications: Add test to check notification language 2023-09-01 16:30:37 +01:00
Dan Brown
4e6b74f2a1 WYSIWYG: Added filtering of page pointer elements
For #4474
2023-09-01 13:50:55 +01:00
omahs
976f241ae0 fix typo 2023-08-31 10:01:56 +02:00
omahs
415dab9936 fix typos 2023-08-31 10:00:45 +02:00
omahs
54715d40ef fix typo 2023-08-31 09:58:59 +02:00
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
joancyho
a0942ef441 Fixed OIDC Logout 2023-08-29 14:58:57 +08:00
joancyho
6b55104ecb Fixed OIDC Logout 2023-08-29 13:07:21 +08: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
JonatanRek
2b604b5af9 Move Manifest Definition to Separate Config File 2023-08-10 17:02:31 +02:00
JonatanRek
08ea97fd83 Manifest Tweaks 2023-08-10 16:43:14 +02:00
JonatanRek
601491b275 Add Color 2023-08-10 15:51:09 +02:00
JonatanRek
88e148ba00 Initial Draft 2023-08-10 15:44:27 +02: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
Lennert Daniels
ac519b3009 Guest create page: name field autofocus 2022-12-02 18:44:17 +01:00
Lennert Daniels
ec3b06d83f Add notice to Page delete confirmation when in use as a template 2022-12-02 18:43:51 +01:00
Lennert Daniels
99ae759eff Prefill new pages with book's default template 2022-12-02 18:42:58 +01:00
Lennert Daniels
1dbc3588cf Add default_template as Book setting 2022-12-02 18:41:59 +01:00
Lennert Daniels
3599a962a3 search-box-cancel placement 2022-12-02 13:10:57 +01: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
009212ab80 Updated version and assets for release v21.11.3 2021-12-15 14:08:37 +00:00
Dan Brown
ba9cb591c8 Merge branch 'master' into release 2021-12-15 14:08:17 +00:00
Dan Brown
632cb71af4 Updated translator attribution before release v21.11.3 2021-12-15 14:07:54 +00:00
Dan Brown
74ab99ec41 Updated php deps 2021-12-15 14:00:30 +00:00
Dan Brown
aa9dafec85 Altered mysql start command in workflows
Due to https://github.com/actions/virtual-environments/issues/4732
2021-12-15 13:56:21 +00:00
Dan Brown
73a37b3cd9 Applied latest StyleCI changes 2021-12-15 13:49:20 +00:00
Dan Brown
e43f679e62 Merge branch 'user_list_control' 2021-12-15 13:47:48 +00:00
Dan Brown
57fc1ba38f New Crowdin updates (#3093)
* New translations auth.php (Vietnamese)

* New translations entities.php (Norwegian Bokmal)

* New translations common.php (Norwegian Bokmal)

* New translations entities.php (Norwegian Bokmal)

* New translations auth.php (Spanish, Argentina)

* New translations entities.php (Spanish, Argentina)

* New translations errors.php (Spanish, Argentina)

* New translations auth.php (Ukrainian)

* New translations auth.php (Ukrainian)

* New translations common.php (Ukrainian)

* New translations entities.php (Ukrainian)

* New translations errors.php (Ukrainian)

* New translations settings.php (Ukrainian)

* New translations validation.php (Ukrainian)

* New translations entities.php (Japanese)

* New translations common.php (Japanese)

* New translations entities.php (Japanese)

* New translations auth.php (Portuguese)

* New translations auth.php (Portuguese)

* New translations common.php (Portuguese)

* New translations entities.php (Portuguese)
2021-12-15 13:46:49 +00:00
Dan Brown
e765e61854 Addressed user detail harvesting issue
Altered access & usage of the /search/users/select endpoint with the
following changes:
- Removed searching of email address to prevent email detail discovery
  via hunting via search queries.
- Required the user to be logged in and have permission to manage users
  or manage permissions on items in some way.
- Removed the user migration option on user delete unless they have
  permission to manage users.

For #3108
Reported in https://huntr.dev/bounties/135f2d7d-ab0b-4351-99b9-889efac46fca/
Reported by @haxatron
2021-12-14 18:47:22 +00: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
Dan Brown
867cbe15ea Added link to OIDC docs in .env.example.complete 2021-12-07 13:45:43 +00:00
Dan Brown
b22dd3cb88 Added url and preview_html params to search API results
Allows easy direct linking and usage of the HTML preview content
we show in the UI when viewing search results.
Note: preview_html content is a rough representation only, it does not
match exactly what was matched in the database-search-operation which
finds the results.

For #3096 and #3080
2021-12-06 20:42:04 +00:00
Dan Brown
d00ac2f34e Updated version and assets for release v21.11.2 2021-11-30 14:30:19 +00:00
Dan Brown
bd4dc6d463 Merge branch 'master' into release 2021-11-30 14:29:53 +00:00
Dan Brown
e6c8ecba9c Merge branch 'master' of github.com:BookStackApp/BookStack 2021-11-30 14:25:27 +00:00
Dan Brown
9490457d04 Applied StyleCI changes 2021-11-30 14:25:09 +00:00
Dan Brown
3e97fdf827 New Crowdin updates (#3076)
* New translations entities.php (Chinese Simplified)

* New translations settings.php (Portuguese, Brazilian)

* New translations validation.php (Portuguese, Brazilian)

* New translations common.php (Chinese Simplified)

* New translations settings.php (Chinese Simplified)

* New translations auth.php (Turkish)
2021-11-30 14:24:35 +00:00
Dan Brown
3b3eb0f44f Updated API session auth to consider public access setting
For #3091
2021-11-30 13:55:56 +00:00
Dan Brown
b4fa82e329 Fixed related permissions query not considering drafts
Page-related items added on drafts could be visible in certain scenarios
since the applied permissions query filters would not consider
page draft visibility.
This commit alters queries on related items to apply such filtering.

Included test to cover API scenario.
Thanks to @haxatron for reporting.
2021-11-30 00:06:17 +00:00
Dan Brown
42703dd859 Tweaked pdf export iframe replacement to fix compatibility
Was using a method that wasn't a proper available part of the
DomElement API.
2021-11-28 21:01:35 +00:00
Dan Brown
2c21850da7 Added conversion of iframes to anchors on PDF export
- Replaced iframe elements with anchor elements wrapped in a paragraph.
- Extracted PDF generation action to seperate class for easier mocking
  within testing.
- Added test to cover.

For #3077
2021-11-25 15:12:32 +00:00
Dan Brown
709533c1fb Fixed up logical theme docs a tad
- Added link to video guide on YouTube.
- Formalised the customCommand docs parts I hastily added before.
2021-11-24 18:58:46 +00:00
Dan Brown
d91180a909 Updated version and assets for release v21.11.1 2021-11-23 20:44:36 +00:00
Dan Brown
bc2913a5cb Merge branch 'master' into release 2021-11-23 20:44:12 +00:00
Dan Brown
cd7788f2e9 Updated translators and merged styleci fixes 2021-11-23 20:41:12 +00:00
Dan Brown
f63d7f60aa New Crowdin updates (#3057)
* New translations auth.php (Chinese Simplified)

* New translations common.php (Chinese Simplified)

* New translations entities.php (Chinese Simplified)

* New translations common.php (Chinese Simplified)

* New translations settings.php (Chinese Simplified)

* New translations activities.php (Chinese Simplified)

* New translations entities.php (Chinese Simplified)

* New translations auth.php (Russian)

* New translations common.php (Russian)

* New translations common.php (Russian)

* New translations entities.php (Russian)

* New translations errors.php (Russian)

* New translations settings.php (Russian)

* New translations auth.php (Italian)

* New translations common.php (Italian)

* New translations entities.php (Italian)

* New translations entities.php (Italian)

* New translations auth.php (Estonian)
2021-11-23 20:38:52 +00:00
Dan Brown
197caddf96 Changed homepage card header links to be bottom-card-links
The old links in the headers were not obvious. This changes the
header-based links to instead be a link at the bottom of the card.

Related to #3046
2021-11-23 18:18:49 +00:00
Dan Brown
096ed722dd Added use of the prefers-contrast media query
Used upon areas we usually fade-out to provide a focused user
experience. If the user desires more contrasted we prevent this
behaviour using the prefers-contrast media query.

Related to #2634
2021-11-23 15:49:54 +00:00
Dan Brown
024924eef3 Applied another round of static analysis updates 2021-11-22 23:33:55 +00:00
Dan Brown
1bf59f434b Tweaked custom command registration, Added StyleCI fixes
Old command registration method was interfering with default commands,
causing only a limited subset of commands to show overall.
This change follows the method the frameworks uses when loading in from a
directory to prevent issues with run/load order.
2021-11-22 22:22:31 +00:00
Dan Brown
c6e196989e Merge pull request #3072 from BookStackApp/logical_theme_commands
Support custom commands via logical theme system
2021-11-22 19:08:15 +00:00
Dan Brown
cb30c258df Added test for logical-theme-system command registration
Changed how the command registration was handled due to complications of
action order found during testing. Now the theme service will resolve
and directly register the command on the Kernel instead of them being
fetched from the ThemeService from within Kernel.
More direct, Seems to work.
2021-11-22 19:03:04 +00:00
Dan Brown
cdaad2f40e Support custom commands via logical theme system
Added initial work to support registering commands through the logical
theme system. Includes docs changes and example.

Not yet covered via testing.
2021-11-22 18:30:58 +00:00
Dan Brown
4ddbc9556b Merge branch 'assign_ids_to_nested_headers' of https://github.com/Julesdevops/BookStack into Julesdevops-assign_ids_to_nested_headers 2021-11-22 16:34:28 +00:00
Dan Brown
9a5adc026a Updated test to ensure autofocus is set on TOTP input 2021-11-22 13:28:46 +00:00
Robert Accettura
37db51a627 Update verify-totp.blade.php 2021-11-21 23:15:37 -05:00
julesdevops
f8c16494fd feat(PageContent): set unique ids on nested headers 2021-11-21 22:45:25 +01:00
Robert Accettura
0d740ca681 Set taborder for TOTP Verification
Adding tabindex=0 means when pressing tab the focus goes right to the TOTP input field.  When using a Password Manager this makes it easier than having to hit tab 3X to get the right focus.
2021-11-21 15:40:11 -05:00
Dan Brown
876bc10d4d Applied another set of static analysis improvements 2021-11-20 14:03:56 +00:00
Dan Brown
754403a29e Added video guide link to visual theme system docs 2021-11-18 21:04:25 +00:00
Dan Brown
4802394562 Updated version and assets for release v21.11 2021-11-16 13:22:24 +00:00
Dan Brown
1755556468 Merge branch 'master' into release 2021-11-16 13:21:44 +00:00
Dan Brown
05ef23d34e New Crowdin updates (#3040) 2021-11-16 12:31:37 +00:00
Dan Brown
79c75f9296 Updated translators and made StyleCI changes 2021-11-16 12:29:50 +00:00
Dan Brown
555723a966 Fixed tags listing grouping by name only on search
Included test to cover case
2021-11-15 19:00:37 +00:00
Dan Brown
056d7c119f Updated php packages 2021-11-15 18:39:38 +00:00
Dan Brown
226f296c9c Removed extra border around markdown editor box 2021-11-15 11:37:17 +00:00
Dan Brown
b546098b36 Fixed page editor back button sometimes going nowhere
Updated the back button to be a proper link instead of a reference to
the last viewed URL since it could break if the last page was the
current one (On validation for example).

Includes test to cover.
Also applied some styleCI changes.

Fixes #2834
2021-11-15 11:19:03 +00:00
Dan Brown
88e6f93abf Prevented auto-login from direct email confirmation actions
Was done for convenience but could potentially be exploited by an
attacker using signing up via one of these routes, then forwarding
an email confirmation to another user so they unknowingly utilise
an account someone else controls.

Tweaks the flow of confirming email, and the user invite flow.

For #3050
2021-11-15 10:50:28 +00:00
Dan Brown
e29d03ae76 Updated page includes to be top-level for code blocks
This change means that code blocks are now included still wrapped in
their pre tags, as we do for tables and lists.
Previously the <code> inner content would be included which would lead
to a generally bad/broken presentation.

Hopefully should not be a breaking change as section include tags for
code was tricky to get to, and it was in a semi-broken state.

For #2406
2021-11-15 00:48:05 +00:00
Dan Brown
85154fff69 Added an env configurable file upload size limit
Replaces the old suggestion of setting JS head 'window.uploadLimit'
variable. This new env option will be used by back-end validation and
front-end libs/logic too.

Limits already likely exist within prod environments at a PHP and
webserver level but this allows an app-level limit and centralises the
option on the BookStack side into the .env

Closes #3033
2021-11-14 22:03:22 +00:00
Dan Brown
f910738a80 Changed logout routes to POST instead of GET
As per #3047.

Also made some SAML specific fixes:
- IDP initiated login was broken due to forced default session value.
  Double checked against OneLogin lib docs that this reverted logic was fine.
- Changed how the saml login flow works to use 'withoutMiddleware' on
  the route instead of hacking out the session driver. This was due to
  the array driver (previously used for the hack) no longer being
  considered non-persistent.
2021-11-14 21:13:24 +00:00
Dan Brown
fceb4ecc07 Fixed sponsor image logo paths
Broke due to website branch name change
2021-11-14 16:53:01 +00:00
Dan Brown
6f1bdbf771 Added API search endpoint
Is a little awkward, emulates a 'list' API endpoint but has unstable
paging and does not support filters/sort. This is detailed on the
endpoint though.

Made some updates to the docs system to better support parameters
and examples on GET requests.

Includes tests to cover.

For #909
2021-11-14 16:28:01 +00:00
Dan Brown
2051189921 Added /api => /api/docs redirect for convenience. 2021-11-14 15:20:04 +00:00
Dan Brown
7025cb38df Removed prefix route groups, applyed styleci changes
Removing prefix route groups out of visual preference.
Those don't really save much and I prefer seeing the complete
paths when going down the list to better guage where I am.
2021-11-14 15:16:18 +00:00
Dan Brown
2e49b16177 Prevented created/update_by filters be wiped in search
Updating filters via sidebar would wipe the created_by/update_by filters
since these were not part of the sidebar filter form.
This adds them, if existing, as hidden inputs.
Includes tests to cover.

Closes #2736
2021-11-14 15:07:13 +00:00
Dan Brown
8e71cd9bac Fixed issue where markdown drafts showed as HTML
Markdown content was not being stored, only the sent
HTML representation, causing the draft to show as HTML upon next edit.
Added test to cover.

Fixes #3054
2021-11-14 12:17:22 +00:00
Dan Brown
89f7f8e259 Hid skip-to-content for print media
Fixes #3051
2021-11-14 11:50:13 +00:00
Dan Brown
f2ee95ca03 Merge pull request #3043 from BookStackApp/search_improvements_a
Search Engine Improvement
2021-11-13 15:13:29 +00:00
Dan Brown
fc7bd57dc8 Fixed occurances of altered titles in search results 2021-11-13 15:04:04 +00:00
Dan Brown
21d3620ef0 Attempted to make test a bit less flaky 2021-11-13 14:51:59 +00:00
Dan Brown
755dc99c72 Made further tweaks to search results formatting
- Updated page names to not be limited to a certain length.
- Added better start/end fill logic.
- Prevented <strong> tags from being counted towards the target content
  length desired from the formatter.
2021-11-13 14:37:40 +00:00
Dan Brown
221458ccfd Fixed failing tests due to search highlighting changes 2021-11-13 13:43:41 +00:00
Dan Brown
2633b94deb Applied StyleCI changes 2021-11-13 13:28:17 +00:00
Dan Brown
63d8d72d7e Added testing to cover search result highlighting 2021-11-13 13:26:11 +00:00
Dan Brown
339518e2a6 Added tag highlighting in search
Using basic match of name or value containing a general term.
2021-11-13 13:02:32 +00:00
Dan Brown
ab4e99bb18 Added name highlighting in search results 2021-11-13 12:44:27 +00:00
Dan Brown
f30b937bb0 Added search result preview text highlighting
Created a new class to manage formatting of content for search results.
Turned out to be quite a complex task. This only does the preview text
so far, not titles or tags.

Not yet tested.
2021-11-12 22:57:50 +00:00
Dan Brown
7d0724e288 Added auto-conversion of search terms to exact values
Will occur when a search term contains a character that's used to split
content into search terms.
Added testing to cover.
2021-11-12 18:03:44 +00:00
Dan Brown
99587a0be6 Added tag values as part of the indexed search terms
This allows finding content via tag name/values when just searching
using normal seach terms.
Added testing to cover.

Related to #1577
2021-11-12 17:06:01 +00:00
Dan Brown
f28daa01d9 Added page content parsing to up-rank header text in search
This adds parsing of page content so that headers apply a boost to
scores in the search term index.
Additionally, this merges title and content terms to reduce the amount
of stored terms a little.
Includes testing to cover.
2021-11-12 13:47:23 +00:00
Dan Brown
820be162f5 Updated regen-search command to show some level of progress 2021-11-11 14:10:11 +00:00
Dan Brown
9f32613982 Refactored search indexer, Increase title/name score boost
- Title score boost changed from 5 to 40 (8x increase).
- Extracted entity parsing to its own function
2021-11-11 13:36:49 +00:00
Dan Brown
0ddd052818 Added missing comments or types
Checked over latest changes for potential SQL injection, all variable
usages are either (from trusted sourced AND case) or using
parameters/bindings to ensure it's handled at driver/lib level.
2021-11-09 15:13:15 +00:00
Dan Brown
da17004c3e Added test to cover search frquency rank changes 2021-11-09 15:05:02 +00:00
Dan Brown
bc472ca2d7 Improved relation loading during search
Relations now loaded during back-end query phase instead of being lazy
loaded one-by-one within views.

Reduced queries in testing from ~60 to ~20.

Need to check other areas list-item.php's "showPath" option is used to
ensure relations are properly loaded for those listings.
2021-11-08 15:24:49 +00:00
Dan Brown
b3e1c7da73 Applied styleci fixes and pluck improvement as per larastan 2021-11-08 15:00:47 +00:00
Dan Brown
7405613f8d Added search term score popularity adjustment
Adds adjustment of search term 'score' (Using in result ranking) so that
a relative 0.3 to 1.3 mulitplier is applied based upon relative
popularity within the whole database. At this point the term popularity
is still done via a prefix match against the search term.

Uses a SUM(IF(cond, a, IF(cond, a, ...))) chain to produce the scoring
result in the select query.
2021-11-08 14:23:48 +00:00
Dan Brown
b0b6f466c1 Reduced data retreived from database on page search 2021-11-08 11:41:14 +00:00
Dan Brown
9e0164f4f4 Further search system refactorings
- Moved search term querying to its own method.
- Updated Large content seeder to be more performant
2021-11-08 11:29:25 +00:00
Dan Brown
e1b8fe45b0 Refactored search runner a little to be neater 2021-11-08 11:04:27 +00:00
Dan Brown
f2b1d2e1e7 Applied latest StyleCI changes 2021-11-06 22:00:33 +00:00
Dan Brown
921e25e7e1 Merge pull request #3042 from BookStackApp/tags_view
Tag view
2021-11-06 21:59:34 +00:00
Dan Brown
899349c4b4 Added testing coverage for tag index
Also:
- Extracted out index table row to its own view.
- Added empty state.
- Ensured query params are set on pagination links.
2021-11-06 21:54:02 +00:00
Dan Brown
f8f9e74992 Added links to tag page
- Added from books/shelves listings and within the tag-edit view for all
  entities.
2021-11-06 20:21:11 +00:00
Dan Brown
929c8312bd Started build of tag view
- Created listing
- Allows drilldown to tag name
- Shows totals

Not yet covered via testing
2021-11-06 16:30:20 +00:00
Dan Brown
8d7c8ac8bf Done a round of phpstan fixes 2021-11-06 00:32:01 +00:00
Dan Brown
5c6a6b50a0 Applied StyleCI changes, added php/larastan to attribution 2021-11-05 16:27:59 +00:00
Dan Brown
bc291bee78 Added inital phpstan/larastan setup 2021-11-05 16:18:06 +00:00
Dan Brown
d0aa10a8c3 Applied styleci changes 2021-11-05 00:28:41 +00:00
Dan Brown
06b5009842 Standardised laravel validation to be array based
Converted from string-only-based validation.
Array based validation works nicer once you have validation classess or
advanced validation options.
2021-11-05 00:26:55 +00:00
Dan Brown
0ba8541370 Updated npm deps 2021-11-04 23:07:36 +00:00
Dan Brown
22024df508 Merge branch 'master' of github.com:BookStackApp/BookStack 2021-11-04 22:58:15 +00:00
Dan Brown
de5322288c Applied latest styleci changes 2021-11-04 22:57:49 +00:00
Dan Brown
9542509584 New Crowdin updates (#3038)
Just crowdin aligning string quote styles
2021-11-04 22:57:04 +00:00
Dan Brown
1eed8d6325 Removed style in discord logo to prevent clash with twitter logo
Both were using the same class names causing a quadrant of the slack logo
to be the discord brand color.

Related to #3032
2021-11-04 22:52:35 +00:00
Dan Brown
b9a58859a4 Merge branch 'modernize-3rd-party-service-logos' of https://github.com/na3shkw/BookStack into na3shkw-modernize-3rd-party-service-logos 2021-11-04 22:45:57 +00:00
Dan Brown
c9c4dbcb5b Merge branch 'laravel_upgrade' 2021-11-04 22:42:35 +00:00
Dan Brown
6f75aa9cdc Reverted shift change to old migration 2021-11-04 22:38:55 +00:00
Dan Brown
9c680efaad Updated php packages, Added php8.1 to GH actions 2021-11-04 22:29:36 +00:00
Dan Brown
cccee0808f Updated API examples with date format changes
Updated to full ISO-8601 to reflect change in Laravel 7.
2021-11-04 22:02:21 +00:00
Dan Brown
01cdbdb7ae Updated version and assets for release v21.10.3 2021-11-01 13:31:10 +00:00
Dan Brown
fc8bbf3eab Merge branch 'master' into release 2021-11-01 13:30:36 +00:00
Dan Brown
a17be959d8 Applied latest styleci changes 2021-11-01 13:26:02 +00:00
Dan Brown
ce3f489188 Merge branch '3027_attachment_vuln' 2021-11-01 13:25:12 +00:00
Dan Brown
f4201e5740 New Crowdin updates (#3023)
* New translations errors.php (Polish)

* New translations activities.php (Dutch)

* New translations auth.php (Dutch)

* New translations common.php (Dutch)

* New translations entities.php (Dutch)

* New translations auth.php (Dutch)

* New translations auth.php (Dutch)

* New translations auth.php (Dutch)

* New translations settings.php (Latvian)
2021-11-01 13:16:15 +00:00
na3shkw
7e2c1b31a1 Modernize third party services' logos 2021-11-01 12:41:23 +00:00
Dan Brown
bfbccbede1 Updated attachments to not be saved with a complete extension
Intended to limit impact in the event the storage path is potentially
exposed.
2021-11-01 11:32:00 +00:00
Dan Brown
4360da03d4 Ran a pass through image and attachment routes
Added some stronger types, formatting changes and simplifications along
the way.
2021-11-01 11:17:30 +00:00
Dan Brown
c7fea8fe08 Cleaned up logic within ImageRepo
- Moved out extension check to ImageService as that seems more relevant.
- Updated models to use static-style references instead of facade to align with common modern usage within the app.
- Updated custom image_extension validation rule to use shared logic in image service.
2021-11-01 00:24:42 +00:00
Dan Brown
43830a372f Updated showImage file serving to not be traversable
For #3030
2021-10-31 23:53:17 +00:00
Dan Brown
ae155d6745 Added safe mime sniffing to prevent serving HTML
(Amoung other content types)
For #3027
2021-10-31 17:58:56 +00:00
Dan Brown
5c834f24a6 Updated AzureAD provider to use microsoft graph
Since AzureAD graph is going away.
Tested using old AzureAD graph usage for backwards-compatbility, did not
seem to break things. Could not test with conditional access though due
to azure never enforcing it no matter what I attempted.

Fpr #3028
2021-10-31 13:09:30 +00:00
Dan Brown
98b23fd7ab Moved from debugbar to clockwork 2021-10-30 22:03:36 +01:00
Dan Brown
f139cded78 Laravel 8 shift squash & merge (#3029)
* Temporarily moved back config path
* Apply Laravel coding style
* Shift exception handler
* Shift HTTP kernel and middleware
* Shift service providers
* Convert options array to fluent methods
* Shift to class based routes
* Shift console routes
* Ignore temporary framework files
* Shift to class based factories
* Namespace seeders
* Shift PSR-4 autoloading
* Shift config files
* Default config files
* Shift Laravel dependencies
* Shift return type of base TestCase methods
* Shift cleanup
* Applied stylci style changes
* Reverted config files location
* Applied manual changes to Laravel 8 shift

Co-authored-by: Shift <shift@laravelshift.com>
2021-10-30 21:29:59 +01:00
Dan Brown
85dc8d9791 Updated sponsor link 2021-10-30 11:51:49 +01:00
Dan Brown
5fd10e695a Added sponsors to readme, updated license file 2021-10-29 21:37:10 +01:00
Dan Brown
3cdab19319 Updated version and assets for release v21.10.2 2021-10-28 15:57:04 +01:00
Dan Brown
5661d20e87 Merge branch 'master' into release 2021-10-28 15:56:49 +01:00
Dan Brown
e7bec79f25 New Crowdin updates (#3014)
* New translations entities.php (Estonian)

* New translations entities.php (Estonian)
2021-10-28 15:55:13 +01:00
Dan Brown
4f55fe2f8e Made further changes to page image extraction validation
Fixes #3019
Increased testing to cover the failing case amoung others.
2021-10-28 15:54:00 +01:00
Dan Brown
91f80123e8 Merge branch 'master' into release 2021-10-27 12:35:00 +01:00
Dan Brown
7a0636d0f8 Updated version and assets for release v21.10.1 2021-10-27 12:31:40 +01:00
Dan Brown
3166541002 Added test to cover #3010 2021-10-27 12:29:01 +01:00
Dan Brown
b31fbf5ba8 Merge branch 'master' of https://github.com/haxatron/BookStack into haxatron_upload_issue 2021-10-27 12:21:27 +01:00
Dan Brown
624d55a773 New Crowdin updates (#3006)
* New translations auth.php (Latvian)

* New translations errors.php (Latvian)

* New translations auth.php (Latvian)

* New translations entities.php (Latvian)

* New translations settings.php (Latvian)

* New translations settings.php (Estonian)

* New translations entities.php (Estonian)

* New translations settings.php (Estonian)

* New translations validation.php (Estonian)

* New translations entities.php (Estonian)

* New translations settings.php (Spanish, Argentina)

* New translations settings.php (Vietnamese)

* New translations settings.php (Slovenian)

* New translations settings.php (Swedish)

* New translations settings.php (Turkish)

* New translations settings.php (Ukrainian)

* New translations settings.php (Chinese Simplified)

* New translations settings.php (Chinese Traditional)

* New translations settings.php (Portuguese, Brazilian)

* New translations settings.php (Russian)

* New translations settings.php (Indonesian)

* New translations settings.php (Persian)

* New translations settings.php (Croatian)

* New translations settings.php (Latvian)

* New translations settings.php (Bosnian)

* New translations settings.php (Norwegian Bokmal)

* New translations settings.php (Slovak)

* New translations settings.php (Portuguese)

* New translations settings.php (Polish)

* New translations settings.php (Catalan)

* New translations settings.php (Estonian)

* New translations settings.php (Japanese)

* New translations settings.php (French)

* New translations settings.php (Spanish)

* New translations settings.php (Arabic)

* New translations settings.php (Bulgarian)

* New translations settings.php (Czech)

* New translations settings.php (Dutch)

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

* New translations settings.php (Lithuanian)

* New translations settings.php (German Informal)

* New translations settings.php (Polish)

* New translations settings.php (French)

* New translations settings.php (German)

* New translations settings.php (German Informal)
2021-10-27 12:17:53 +01:00
Dan Brown
f77236aa38 Laravel 7.x Shift (#3011)
* Apply Laravel coding style
* Shift bindings
* Shift core files
* Shift to Throwable
* Add laravel/ui dependency
* Shift Eloquent methods
* Shift config files
* Shift Laravel dependencies
* Shift cleanup
* Shift test config and references
* Applied styleci changes
* Applied fixes post shift to laravel 7

Co-authored-by: Shift <shift@laravelshift.com>
2021-10-26 22:04:18 +01:00
Dan Brown
42f0ba1875 Added security policy md file 2021-10-26 16:09:41 +01:00
Dan Brown
0d312e5348 Merge pull request #3008 from IndrekHaav/et-typo
Minor capitalisation fix for Estonian
2021-10-26 13:33:27 +01:00
Dan Brown
7b244ea012 Updated php deps
Also removes abandoned status of sebastian/resource-operations as per
issue #3007
2021-10-26 13:12:40 +01:00
Indrek Haav
538b5ef4eb Minor capitalisation fix for Estonian 2021-10-26 15:09:38 +03:00
Haxatron
64937ab826 Update ImageRepo.php
fix image validation vulnerability
2021-10-26 09:39:16 +08:00
Dan Brown
0fe5bdfbac Updated version and assets for release v21.10 2021-10-25 15:59:23 +01:00
Dan Brown
f88687e977 Merge branch 'master' into release 2021-10-25 15:58:59 +01:00
Dan Brown
a5401eb00a New Crowdin updates (#3005)
* New translations settings.php (Spanish, Argentina)

* New translations settings.php (Polish)

* New translations settings.php (Estonian)

* New translations errors.php (Spanish, Argentina)

* New translations settings.php (Japanese)

* New translations activities.php (German Informal)

* New translations auth.php (German Informal)

* New translations settings.php (French)

* New translations settings.php (Spanish)

* New translations settings.php (Arabic)

* New translations settings.php (Bulgarian)

* New translations settings.php (Catalan)

* New translations settings.php (Norwegian Bokmal)

* New translations settings.php (German Informal)

* New translations settings.php (Bosnian)

* New translations settings.php (Czech)

* New translations settings.php (Slovak)

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

* New translations settings.php (Lithuanian)

* New translations settings.php (Dutch)

* New translations settings.php (Portuguese)

* New translations settings.php (Russian)

* New translations settings.php (Slovenian)

* New translations settings.php (Latvian)

* New translations settings.php (Swedish)

* New translations settings.php (Turkish)

* New translations settings.php (Ukrainian)

* New translations settings.php (Chinese Simplified)

* New translations settings.php (Chinese Traditional)

* New translations settings.php (Vietnamese)

* New translations settings.php (Portuguese, Brazilian)

* New translations settings.php (Indonesian)

* New translations settings.php (Persian)

* New translations settings.php (Croatian)

* New translations validation.php (German Informal)
2021-10-25 15:01:32 +01:00
Dan Brown
fa466139f0 Updated translators before v21.10 release 2021-10-25 14:49:21 +01:00
Dan Brown
a75cfd1f25 Added estonian to language logic 2021-10-25 14:49:03 +01:00
Dan Brown
9c2b8057ab New Crowdin updates (#2983)
* New translations auth.php (Polish)

* New translations common.php (Polish)

* New translations entities.php (Polish)

* New translations auth.php (Polish)

* New translations common.php (Polish)

* New translations settings.php (Polish)

* New translations validation.php (Polish)

* New translations activities.php (Estonian)

* New translations auth.php (Estonian)

* New translations common.php (Estonian)

* New translations components.php (Estonian)

* New translations entities.php (Estonian)

* New translations errors.php (Estonian)

* New translations pagination.php (Estonian)

* New translations passwords.php (Estonian)

* New translations settings.php (Estonian)

* New translations validation.php (Estonian)

* New translations activities.php (Estonian)

* New translations activities.php (Estonian)

* New translations auth.php (Estonian)

* New translations common.php (Estonian)

* New translations components.php (Estonian)

* New translations entities.php (Estonian)

* New translations pagination.php (Estonian)

* New translations passwords.php (Estonian)

* New translations entities.php (Estonian)

* New translations errors.php (Estonian)

* New translations validation.php (Estonian)

* New translations settings.php (Estonian)

* New translations auth.php (Estonian)

* New translations entities.php (Estonian)

* New translations passwords.php (Estonian)

* New translations settings.php (Estonian)

* New translations auth.php (Estonian)

* New translations entities.php (Estonian)

* New translations errors.php (Estonian)

* New translations settings.php (Estonian)

* New translations settings.php (Estonian)

* New translations errors.php (German)

* New translations errors.php (Portuguese, Brazilian)

* New translations errors.php (Swedish)

* New translations errors.php (Turkish)

* New translations errors.php (Ukrainian)

* New translations errors.php (Chinese Simplified)

* New translations errors.php (Chinese Traditional)

* New translations errors.php (Vietnamese)

* New translations errors.php (Indonesian)

* New translations errors.php (Slovak)

* New translations errors.php (Persian)

* New translations errors.php (Spanish, Argentina)

* New translations errors.php (Croatian)

* New translations errors.php (Latvian)

* New translations errors.php (Bosnian)

* New translations errors.php (Norwegian Bokmal)

* New translations errors.php (Slovenian)

* New translations errors.php (Russian)

* New translations errors.php (Estonian)

* New translations errors.php (Danish)

* New translations errors.php (French)

* New translations errors.php (Spanish)

* New translations errors.php (Arabic)

* New translations errors.php (Bulgarian)

* New translations errors.php (Catalan)

* New translations errors.php (Czech)

* New translations errors.php (Hebrew)

* New translations errors.php (Portuguese)

* New translations errors.php (Hungarian)

* New translations errors.php (Italian)

* New translations errors.php (Japanese)

* New translations errors.php (Korean)

* New translations errors.php (Lithuanian)

* New translations errors.php (Dutch)

* New translations errors.php (Polish)

* New translations errors.php (German Informal)

* New translations errors.php (Spanish)

* New translations auth.php (Estonian)

* New translations entities.php (Estonian)

* New translations errors.php (Estonian)

* New translations activities.php (Japanese)

* New translations activities.php (Japanese)

* New translations auth.php (Japanese)

* New translations components.php (Japanese)

* New translations passwords.php (Japanese)

* New translations errors.php (Estonian)

* New translations settings.php (Estonian)

* New translations validation.php (Estonian)

* New translations errors.php (French)

* New translations activities.php (Japanese)

* New translations settings.php (Japanese)

* New translations entities.php (Japanese)

* New translations settings.php (Japanese)

* New translations common.php (Japanese)

* New translations settings.php (Japanese)

* New translations settings.php (Japanese)

* New translations entities.php (Japanese)

* New translations settings.php (Japanese)

* New translations settings.php (Japanese)

* New translations entities.php (Japanese)

* New translations settings.php (Japanese)

* New translations common.php (Japanese)

* New translations errors.php (Polish)

* New translations auth.php (Estonian)

* New translations components.php (Estonian)

* New translations entities.php (Estonian)

* New translations validation.php (Estonian)

* New translations errors.php (Estonian)

* New translations settings.php (Estonian)

* New translations errors.php (Chinese Simplified)

* New translations auth.php (Japanese)

* New translations auth.php (Japanese)

* New translations common.php (Japanese)

* New translations entities.php (Japanese)

* New translations errors.php (Italian)

* New translations common.php (Japanese)

* New translations auth.php (Italian)

* New translations entities.php (Italian)

* New translations entities.php (Japanese)

* New translations settings.php (Japanese)

* New translations common.php (Japanese)

* New translations entities.php (Japanese)

* New translations entities.php (Estonian)

* New translations settings.php (Estonian)

* New translations validation.php (Japanese)

* New translations errors.php (Japanese)

* New translations validation.php (Japanese)

* New translations auth.php (Japanese)

* New translations settings.php (Japanese)

* New translations activities.php (Indonesian)

* New translations auth.php (Indonesian)

* New translations validation.php (Estonian)

* New translations settings.php (Estonian)
2021-10-25 13:51:27 +01:00
Dan Brown
31ba972cfc Tweaked sidepart list item padding, Review of #3000
- Scoped padding change to just entity-list-items within the sidebar
  side reduction of right-hand-padding to zero was causing other
  entity-list-items, such as those in the homepage listing, would then
  have no padding.
- Updated styles to use css logical properties to retain support for RTL
  languages such as Arabic, where the whole interface flips around.
  Related: https://css-tricks.com/css-logical-properties-and-values/
2021-10-23 22:03:03 +01:00
Dan Brown
f73b82ee57 Merge branch 'fix_sidebar_css' of https://github.com/ffranchina/BookStack into ffranchina-fix_sidebar_css 2021-10-23 21:54:25 +01:00
Dan Brown
98072ba4a9 Reviewed SAML SLS changes for ADFS, #2902
- Migrated env usages to config.
- Removed potentially unneeded config options or auto-set signed options
  based upon provision of certificate.
- Aligned SP certificate env option naming with similar IDP option.

Tested via AFDS on windows server 2019. To test on other providers.
2021-10-23 17:26:01 +01:00
Francesco Franchina
0b15e2bf1c Fixes padding issues of the sidebar's items 2021-10-22 01:34:41 +02:00
Dan Brown
2e9ac21b38 Merge branch 'master' of https://github.com/theodor-franke/BookStack into theodor-franke-master 2021-10-21 14:04:23 +01:00
Dan Brown
129f3286d9 Applied styleci changes 2021-10-20 13:40:27 +01:00
Dan Brown
fe07cdaa06 Merge pull request #2996 from BookStackApp/saml2_acs_session
Updated SAML ACS post to retain user session
2021-10-20 13:38:35 +01:00
Dan Brown
cdef1b3ab0 Updated SAML ACS post to retain user session
Session was being lost due to the callback POST request cookies
not being provided due to samesite=lax. This instead adds an additional
hop in the flow to route the request via a GET request so the session is
retained. SAML POST data is stored encrypted in cache via a unique ID
then pulled out straight afterwards, and restored into POST for the SAML
toolkit to validate.

Updated testing to cover.
2021-10-20 13:34:00 +01:00
Dan Brown
859934d6a3 Applied latest changes from styleCI 2021-10-20 10:49:45 +01:00
Dan Brown
7bbcaa7cbc Merge pull request #2986 from BookStackApp/attachments_api
Attachments API
2021-10-20 10:46:35 +01:00
Dan Brown
7e28c76e6f Adjusted API docs table 2021-10-20 10:46:06 +01:00
Dan Brown
60d4c5902b Added attachment API examples during manual testing 2021-10-20 10:43:03 +01:00
Dan Brown
2409d1850f Added TestCase for attachments API methods 2021-10-20 00:58:56 +01:00
Dan Brown
c699f176bc Fixed bug report yaml formatting 2021-10-19 15:15:35 +01:00
Dan Brown
72ad87b123 Update support_request.yml 2021-10-19 14:52:00 +01:00
Dan Brown
5d6d7ef5a7 Converted issues templates to forms
Added support request template
2021-10-19 14:49:49 +01:00
Dan Brown
7ad98fc3c3 Update language_request.yml 2021-10-19 14:07:45 +01:00
Dan Brown
0d6f1638fe Delete language_request.md 2021-10-19 14:06:53 +01:00
Dan Brown
5a4b366e56 Create language_request.yml 2021-10-19 14:05:34 +01:00
Dan Brown
32f6ea946f Build out core attachments API controller
Related to #2942
2021-10-18 17:46:55 +01:00
Dan Brown
1a8a6c609a Added phpseclib to readme 2021-10-18 11:43:54 +01:00
Dan Brown
cb45c53029 Added base64 image extraction to markdown page content
- Included tests to cover.
- Manually tested via API update and interface page update.

Closes #2898
2021-10-18 11:42:50 +01:00
Dan Brown
6e325de226 Applied latest styles changes from style CI 2021-10-16 16:01:59 +01:00
Dan Brown
263384cf99 Merge branch 'oidc' 2021-10-16 15:51:13 +01:00
Dan Brown
68d437d05b Updated version and assets for release v21.08.6 2021-10-15 14:34:44 +01:00
Dan Brown
1e56aaea04 Merge branch 'master' into release 2021-10-15 14:34:23 +01:00
Dan Brown
5ba964b677 Updated readme with latest version info
Also updated version file to be current
2021-10-15 14:30:49 +01:00
Dan Brown
5647a8a091 New Crowdin updates (#2980)
* New translations entities.php (Spanish, Argentina)

* New translations activities.php (Spanish, Argentina)

* New translations auth.php (Spanish, Argentina)

* New translations settings.php (Spanish, Argentina)

* New translations validation.php (Spanish, Argentina)

* New translations auth.php (Spanish, Argentina)
2021-10-15 14:17:32 +01:00
Dan Brown
f3c147d33b Applied latest styleci changes 2021-10-15 14:16:45 +01:00
Dan Brown
747f81d5d8 Updated php dependancies 2021-10-15 13:15:32 +01:00
Dan Brown
c9c0e5e16f Fixed guest user email showing in TOTP setup url
- Occured during enforced MFA setup upon login.
- Added test to cover.

Fixes #2971
2021-10-14 18:02:16 +01:00
Dan Brown
d21b60079c Merge pull request #2977 from BookStackApp/custom_debug_view
Added custom whoops-based debug view
2021-10-14 17:41:06 +01:00
Dan Brown
ffa4377e65 Added testing to cover debug view 2021-10-14 17:40:22 +01:00
Dan Brown
9b8bb49a33 Added custom whoops-based debug view
Provides a simple bookstack focused view that does not rely on JavaScript.
Contains links to BookStack specific resources in addition to commonly
desired debug details.
2021-10-14 15:33:08 +01:00
Dan Brown
855409bc4f Fixed lack of oidc discovery filtering during testing
Tested oidc system on okta, Keycloak & Auth0
2021-10-14 13:37:55 +01:00
Dan Brown
a5d72aa458 Fleshed out testing for OIDC system 2021-10-13 16:51:27 +01:00
Dan Brown
c167f40af3 Renamed OIDC files to all be aligned 2021-10-12 23:04:28 +01:00
Dan Brown
06a0d829c8 Added OIDC basic autodiscovery support 2021-10-12 23:00:52 +01:00
Dan Brown
790723dfc5 Added further OIDC core class testing 2021-10-12 16:48:54 +01:00
Dan Brown
f3d54e4a2d Added positive test case for OIDC implementation
- To continue coverage and spec cases next.
2021-10-12 00:01:51 +01:00
Dan Brown
6b182a435a Got OIDC custom solution to a functional state
- Validation of all key/token elements now in place.
- Signing key system updated to work with jwk-style array or with
  file:// path to pem key.
2021-10-11 23:00:45 +01:00
Dan Brown
8c01c55684 Added token and key handling elements for oidc jwt
- Got basic signing support and structure checking done.
- Need to run through actual claim checking before providing details
  back to app.
2021-10-11 19:05:16 +01:00
Dan Brown
69301f7575 Merge pull request #2965 from Haxatron/master
Update DOMPDF chroot directory
2021-10-11 10:25:28 +01:00
Dan Brown
8ce696dff6 Started on a custom oidc oauth provider 2021-10-10 19:14:08 +01:00
Haxatron
b043257d9a Update dompdf.php
base_path => public_path
2021-10-10 01:06:08 +08:00
Dan Brown
ca764caf2d Added throttling to password reset requests 2021-10-08 23:19:37 +01:00
Dan Brown
dab170a6fe Updated version and assets for release v21.08.5 2021-10-08 22:25:36 +01:00
Dan Brown
a8de717d9b Merge branch 'master' into release 2021-10-08 22:25:05 +01:00
Dan Brown
543ea6ef71 Updated translator attribution before release v21.08.5 2021-10-08 22:24:32 +01:00
Dan Brown
a9b3df537f Applied changes from styleci 2021-10-08 22:23:17 +01:00
Dan Brown
c2339ac9db New Crowdin updates (#2953)
* New translations settings.php (Chinese Simplified)

* New translations entities.php (Slovak)

* New translations entities.php (Portuguese, Brazilian)

* New translations entities.php (Slovenian)

* New translations entities.php (Swedish)

* New translations entities.php (Turkish)

* New translations entities.php (Ukrainian)

* New translations entities.php (Chinese Simplified)

* New translations entities.php (Chinese Traditional)

* New translations entities.php (Indonesian)

* New translations entities.php (Portuguese)

* New translations entities.php (Persian)

* New translations entities.php (Spanish, Argentina)

* New translations entities.php (Croatian)

* New translations entities.php (Latvian)

* New translations entities.php (Bosnian)

* New translations entities.php (Norwegian Bokmal)

* New translations entities.php (Russian)

* New translations entities.php (Polish)

* New translations entities.php (Vietnamese)

* New translations entities.php (Danish)

* New translations entities.php (French)

* New translations entities.php (Spanish)

* New translations entities.php (Arabic)

* New translations entities.php (Bulgarian)

* New translations entities.php (Catalan)

* New translations entities.php (Czech)

* New translations entities.php (German)

* New translations entities.php (Dutch)

* New translations entities.php (Hebrew)

* New translations entities.php (Hungarian)

* New translations entities.php (Italian)

* New translations entities.php (Japanese)

* New translations entities.php (Korean)

* New translations entities.php (Lithuanian)

* New translations entities.php (German Informal)

* New translations entities.php (French)

* New translations entities.php (Spanish)

* New translations settings.php (Czech)

* New translations entities.php (Czech)

* New translations activities.php (Czech)

* New translations auth.php (Czech)

* New translations common.php (Czech)

* New translations validation.php (Czech)

* New translations entities.php (Portuguese)

* New translations settings.php (Portuguese)

* New translations entities.php (Portuguese)

* New translations activities.php (Portuguese)

* New translations auth.php (Portuguese)

* New translations common.php (Portuguese)

* New translations validation.php (Portuguese)

* New translations entities.php (Chinese Simplified)

* New translations entities.php (Chinese Simplified)

* New translations activities.php (Ukrainian)

* New translations activities.php (Ukrainian)
2021-10-08 22:22:01 +01:00
Dan Brown
41541df6ec Added testing to cover work done in last commit
Relevant to comments in 7224fbcc89.
Added test cases. Ensured they failed pre-commit.
Also tested a range of the altered endpoints manually on both local and
s3-like filesystems.
2021-10-08 21:47:59 +01:00
Dan Brown
7224fbcc89 Added protections against path traversal in file system operations
- Files within the storage/ path could be accessed via path traversal
  references in content, accessed upon HTML export.
- This addresses this via two layers:
  - Scoped local flysystem filesystems down to the specific image &
    file folders since flysystem has built-in checking against the
    escaping of the root folder.
  - Added path normalization before enforcement of uploads/{images,file}
    prefix to prevent traversal at a path level.

Thanks to @Haxatron via huntr.dev for discovery and reporting.
Ref: https://huntr.dev/bounties/ac268a17-72b5-446f-a09a-9945ef58607a/
2021-10-08 17:47:14 +01:00
Dan Brown
81d6b1b016 Fixed search query issues when table prefixes are used
- Old raw select query was causing bad select clause in query
  when table prefixes were active.
2021-10-08 15:25:12 +01:00
Dan Brown
41ac69adb1 Forced response cache revalidation on logged-in responses
- Prevents authenticated responses being visible when back button
  pressed in browser.
- Previously, 'no-cache, private' was added by default by Symfony which
  would have prevents proxy cache issues but this adds no-store and a
  max-age option to also invalidate all caching.

Thanks to @haxatron via huntr.dev
Ref: https://huntr.dev/bounties/6cda9df9-4987-4e1c-b48f-855b6901ef53/
2021-10-08 15:22:09 +01:00
Dan Brown
41438adbd1 Continued review of #2169
- Removed uneeded custom refresh or logout actions for OIDC.
- Restructured how the services and guards are setup for external auth
  systems. SAML2 and OIDC now directly share a lot more logic.
- Renamed any OpenId references to OIDC or OpenIdConnect
- Removed non-required CSRF excemption for OIDC

Not tested, Come to roadblock due to lack of PHP8 support in upstream
dependancies. Certificate was deemed to be non-valid on every test
attempt due to changes in PHP8.
2021-10-06 23:05:26 +01:00
Dan Brown
2ec0aa85ca Started refactor for merge of OIDC
- Made oidc config more generic to not be overly reliant on the library
  based upon learnings from saml2 auth.
- Removed any settings that are redundant or not deemed required for
  initial implementation.
- Reduced some methods down where not needed.
- Renamed OpenID to OIDC
- Updated .env.example.complete to align with all options and their
  defaults

Related to #2169
2021-10-06 17:12:01 +01:00
Dan Brown
193d7fb3fe Merge branch 'openid' of https://github.com/jasperweyne/BookStack into jasperweyne-openid 2021-10-06 13:18:21 +01:00
Dan Brown
55be75dee2 Merge pull request #2957 from BookStackApp/dependabot/composer/composer/composer-2.1.9
Bump composer/composer from 2.1.8 to 2.1.9
2021-10-06 10:52:02 +01:00
dependabot[bot]
644bbebb6e Bump composer/composer from 2.1.8 to 2.1.9
Bumps [composer/composer](https://github.com/composer/composer) from 2.1.8 to 2.1.9.
- [Release notes](https://github.com/composer/composer/releases)
- [Changelog](https://github.com/composer/composer/blob/master/CHANGELOG.md)
- [Commits](https://github.com/composer/composer/compare/2.1.8...2.1.9)

---
updated-dependencies:
- dependency-name: composer/composer
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-10-05 20:57:31 +00:00
Dan Brown
f99af807d0 Reviewed and refactored additional editor draft save warnings
- Added testing to cover warning cases.
- Refactored logic to be simpler and move much of the business out of
  the controller.
- Added new message that's more suitable to the case this was handling.
- For detecting an outdated draft, checked the draft created_at time
  instead of updated_at to better fit the scenario being checked.
- Updated some method types to align with those potentially being used
  in the logic of the code.
- Added a cache of shown messages on the front-end to prevent them
  re-showing on every save during the session, even if dismissed.
2021-10-04 20:26:55 +01:00
Dan Brown
756b55bbff Merge branch 'conflict_warnings' of https://github.com/MatthieuParis/BookStack into MatthieuParis-conflict_warnings 2021-10-04 17:10:40 +01:00
Dan Brown
78fe95b6fc Updated version and assets for release v21.08.4 2021-10-04 16:25:24 +01:00
Dan Brown
e0c24e41aa Merge branch 'master' into release 2021-10-04 16:24:54 +01:00
Dan Brown
e37bbf2925 Updated translator attribution before release v21.08.4 2021-10-04 16:24:17 +01:00
Dan Brown
ec61e45a2b New Crowdin updates (#2926)
* New translations settings.php (French)

* New translations auth.php (French)

* New translations settings.php (French)

* New translations entities.php (French)

* New translations activities.php (French)

* New translations common.php (French)

* New translations entities.php (French)

* New translations common.php (French)

* New translations components.php (French)

* New translations settings.php (French)

* New translations auth.php (French)

* New translations settings.php (Russian)

* New translations validation.php (Russian)

* New translations settings.php (Russian)

* New translations auth.php (Russian)

* New translations settings.php (Russian)

* New translations auth.php (Russian)

* New translations entities.php (French)

* New translations auth.php (French)

* New translations entities.php (French)

* New translations auth.php (French)

* New translations settings.php (French)

* New translations validation.php (French)

* New translations settings.php (French)

* New translations entities.php (French)

* New translations errors.php (French)

* New translations passwords.php (French)

* New translations settings.php (French)

* New translations entities.php (French)

* New translations settings.php (French)

* New translations entities.php (German)

* New translations settings.php (German)

* New translations entities.php (German Informal)

* New translations settings.php (German Informal)

* New translations settings.php (German)

* New translations settings.php (German Informal)

* New translations settings.php (French)

* New translations settings.php (Vietnamese)

* New translations settings.php (Slovenian)

* New translations settings.php (Swedish)

* New translations settings.php (Turkish)

* New translations settings.php (Ukrainian)

* New translations settings.php (Chinese Simplified)

* New translations settings.php (Chinese Traditional)

* New translations settings.php (Portuguese, Brazilian)

* New translations settings.php (Portuguese)

* New translations settings.php (Indonesian)

* New translations settings.php (Persian)

* New translations settings.php (Spanish, Argentina)

* New translations settings.php (Croatian)

* New translations settings.php (Latvian)

* New translations settings.php (Bosnian)

* New translations settings.php (Slovak)

* New translations settings.php (Polish)

* New translations settings.php (Russian)

* New translations settings.php (Czech)

* New translations settings.php (German)

* New translations settings.php (German Informal)

* New translations settings.php (Spanish)

* New translations settings.php (Arabic)

* New translations settings.php (Bulgarian)

* New translations settings.php (Catalan)

* New translations settings.php (Danish)

* New translations settings.php (Dutch)

* New translations settings.php (Hebrew)

* New translations settings.php (Hungarian)

* New translations settings.php (Italian)

* New translations settings.php (Japanese)

* New translations settings.php (Korean)

* New translations settings.php (Lithuanian)

* New translations settings.php (Norwegian Bokmal)

* New translations settings.php (Spanish)

* New translations activities.php (Slovak)

* New translations errors.php (Slovak)

* New translations settings.php (Slovak)

* New translations auth.php (Slovak)

* New translations common.php (Slovak)

* New translations entities.php (Slovak)

* New translations settings.php (Slovak)

* New translations activities.php (Slovak)

* New translations settings.php (French)

* New translations settings.php (Russian)

* New translations settings.php (German)

* New translations settings.php (Polish)

* New translations validation.php (Polish)

* New translations auth.php (Vietnamese)

* New translations auth.php (Vietnamese)

* New translations activities.php (Vietnamese)

* New translations common.php (Vietnamese)

* New translations entities.php (Vietnamese)

* New translations settings.php (Chinese Simplified)

* New translations settings.php (Italian)

* New translations auth.php (Italian)

* New translations common.php (Italian)

* New translations common.php (German)

* New translations common.php (German Informal)

* New translations settings.php (German)

* New translations common.php (German)

* New translations common.php (German Informal)

* New translations errors.php (German)
2021-10-04 16:22:16 +01:00
Dan Brown
d3a9645161 Allowed page includes on custom home
For #2279
Old hold-over for when include content permissions were handled less
delicately.
2021-10-04 11:26:26 +01:00
Dan Brown
505d7e604e Applied StyleCI changes 2021-09-29 23:53:11 +01:00
Dan Brown
025442fcd9 Reviewed addition to db table prefix
Review of #2935

- Removed from .env files and added warnings for use if found in config
  file.
- Updated permission service to use whereColumn queries to auto-handle
  use of prefixes.
2021-09-29 18:41:11 +01:00
Dan Brown
0f66c8a0cc Merge branch 'floviolleau-db-prefixes' of https://github.com/floviolleau/BookStack into floviolleau-floviolleau-db-prefixes 2021-09-29 18:13:38 +01:00
Dan Brown
887a79f130 Reviewed adding IP recording to activity & audit log
Review of #2936

- Added testing to cover
- Added APP_PROXIES to .env.example.complete with details.
- Renamed migration to better align the name and to set the migration
  date to fit with production deploy order.
- Removed index from IP column in migration since an index does not yet
  provide any value.
- Updated table header text label.
- Prevented IP recording when in demo mode.
2021-09-26 17:18:12 +01:00
Dan Brown
8972f7b212 Merge branch 'log-ip-address' of https://github.com/johnroyer/BookStack into johnroyer-log-ip-address 2021-09-26 16:17:28 +01:00
Dan Brown
c100560bd9 Applied style ci changes again 2021-09-26 15:49:25 +01:00
Dan Brown
05d99a312d Applied styleci changes 2021-09-26 15:48:22 +01:00
Dan Brown
5c7eb0df57 Caught old string helper function usage
Found by Laravel Shift Workbench
2021-09-26 15:41:11 +01:00
Dan Brown
c32b315cd7 Standardised facade usage to use via their FQCN
Done via Laravel Shift Workbench
2021-09-26 15:37:55 +01:00
Zero
c0da5616f3 Fix coding style 2021-09-23 11:07:13 +08:00
Zero
6418824139 Update translation file 2021-09-20 11:29:14 +08:00
Zero
b834f58e87 Add user IP into audit table 2021-09-20 11:29:14 +08:00
Zero
8efaeb068b Save user IP to audit log 2021-09-20 11:29:14 +08:00
Zero
5cf0c99e32 Add IP column 2021-09-20 11:29:14 +08:00
floviolleau
dbfa2d58ed Allow to use DB tables prefix 2021-09-19 14:33:54 +02:00
floviolleau
f8abad1e3b Allow to use DB tables prefix 2021-09-19 14:32:35 +02:00
floviolleau
1a8ae41263 Allow to use DB tables prefix 2021-09-19 14:31:18 +02:00
floviolleau
00af40ab14 Allow to use DB tables prefix 2021-09-19 14:28:57 +02:00
Dan Brown
ffdfdc7449 Fixed dodgy test helper signature causing tests to fail
Just needed some argument defaults to make them optional for existing
uses.
2021-09-18 21:29:42 +01:00
Dan Brown
ba075b46f9 Merge pull request #2928 from BookStackApp/browserkit_removal
Convert old BrowserKit tests
2021-09-18 21:28:16 +01:00
Dan Brown
c08c8d7aa3 Applied styleci style changes 2021-09-18 21:21:44 +01:00
Dan Brown
6454e24657 Removed browserkit testing from project
Converted last bits of the roles tests and removed dependancies.
Updated other PHP dependancies at the same time.
2021-09-18 21:20:38 +01:00
Dan Brown
d74255df5d Started updating RolesTest away from Browserkit 2021-09-18 00:33:03 +01:00
Dan Brown
a4d9bca9e1 Converted AuthTest away from BrowserKit
Moved some user managment tests out to more relevant classess along the
way.
Found some tweaks to make for email confirmation routing as part of
this.
2021-09-17 23:44:54 +01:00
Dan Brown
90c759e5ca Rewrote entity permissions tests to be non-browser-kit 2021-09-17 22:35:28 +01:00
Dan Brown
5d93dd258e Finished moving EntityTests out to new TestCase files 2021-09-17 21:29:16 +01:00
Dan Brown
de8cceb0f7 Moved more tests out of EntityTest 2021-09-15 22:18:37 +01:00
Dan Brown
8a7408bd31 Fixed social auth login audit log messages
Was logging the whole social account instance instead of just the
method.
Updated tests to cover.

Fixes #2930
2021-09-15 20:55:10 +01:00
Dan Brown
121a746d59 Moved/Updated old Activity tracking tests, started on entity tests
Started moving old EntityTests into more appropriate places within
non-browserkit-test classes. Still many more to do.
2021-09-13 23:26:39 +01:00
Dan Brown
badaf08e55 Removed browserkit from a couple of classess
Done a little reorganisation while there of misplaced tests.
Moved MarkdownTest to a new PageEditorTest to avoid confusion with
other markdown elements and to align with other page tests.
2021-09-13 22:54:21 +01:00
Dan Brown
8565187138 Added border to generated TOTP QR code
To fix QR code not being scannable when in dark mode due to
lack of border matching background of QR code.

Fixes #2925
2021-09-13 14:23:54 +01:00
Dan Brown
fa8553839b Updated version and assets for release v21.08.3 2021-09-12 16:31:02 +01:00
Dan Brown
b8fcefc794 Merge branch 'master' into release 2021-09-12 16:30:35 +01:00
Dan Brown
2eafd8335c Updated translators for v21.08.3 2021-09-12 16:25:33 +01:00
Dan Brown
e2f9089f56 New Crowdin updates (#2915)
* New translations auth.php (Spanish)

* New translations activities.php (Italian)

* New translations settings.php (Italian)

* New translations entities.php (Italian)

* New translations validation.php (Italian)

* New translations activities.php (Danish)

* New translations auth.php (Danish)

* New translations common.php (Danish)

* New translations settings.php (Danish)

* New translations entities.php (Danish)

* New translations auth.php (Danish)

* New translations common.php (Danish)

* New translations errors.php (Danish)

* New translations validation.php (Danish)

* New translations activities.php (Russian)

* New translations auth.php (French)

* New translations auth.php (French)

* New translations settings.php (French)

* New translations entities.php (French)

* New translations auth.php (French)
2021-09-12 16:25:05 +01:00
Dan Brown
ef459ca4c4 Altered the parsing of custom head to prevent htmlentities on content
Was causing things like emjoi within script content to be somewhat
mangled. Instead we force UTF8 only parsing via XML declaration.

Added test to cover.

For #2923
2021-09-12 16:19:17 +01:00
Dan Brown
fb80bb5d58 Applied latest styleci changes 2021-09-06 22:19:06 +01:00
Dan Brown
88c698796b Fixed issue with HTML tags in custom head scripts
Fixes a strange issue of HTML tags within script tags being malformed
when part of the HTML custom head content due to the PHP parsing we do.
DOMDocument seemed to cause this upon load.
Adding LIBXML_SCHEMA_CREATE to the ->loadHTML call seems to fix this but
not really sure why. Doesn't seem to cause further issues though.
Tested with multiple scripts and styles and comments and meta tags.

- Also added new testing class to cover.
- As part of testing, added new folder within tests to house setting
  specific tests.

For #2914
2021-09-05 23:52:39 +01:00
Dan Brown
88bcb68fcb Updated version and assets for release v21.08.2 2021-09-04 15:07:20 +01:00
Dan Brown
7c000553ae Merge branch 'master' into release 2021-09-04 15:06:33 +01:00
Dan Brown
d815e1b9f2 Merge branch 'html-filtering' 2021-09-04 14:53:46 +01:00
Dan Brown
492af79c27 Added a couple of additional CSP rules
As per guidance from google's CSP evaluator.
2021-09-04 14:34:43 +01:00
Dan Brown
253f386f00 Finished off script CSP rules
- Added caching for custom html head parsing to add nonce.
- Also moved api docs page into web routes to prevent issues.
2021-09-04 13:57:04 +01:00
Dan Brown
fd44e4ba74 Started application of CSP headers 2021-09-03 23:32:42 +01:00
Dan Brown
040997fdc4 Added filter for xlink:href svg xss
Simply remove all such attributes
2021-09-03 22:34:49 +01:00
Dan Brown
5e6092aaf8 Added extra HTML filtering of dangerous content
In particular, That around the casing of dangerous values within
attributes. This uses some xpath translation to handle different casing
in contains searching.
2021-09-02 22:02:30 +01:00
Dan Brown
391fa35c80 Updated version and assets for release v21.08.1 2021-09-02 21:13:09 +01:00
Dan Brown
c6773a8c9f Merge branch 'master' into release 2021-09-02 21:12:06 +01:00
Dan Brown
a579b7da21 Updated translator attribution before release v21.08.1 2021-09-02 21:11:23 +01:00
Dan Brown
bc34914ac1 New Crowdin updates (#2906)
* New translations auth.php (Chinese Simplified)

* New translations auth.php (Chinese Simplified)

* New translations validation.php (Chinese Simplified)

* New translations activities.php (Latvian)

* New translations auth.php (Latvian)

* New translations common.php (Latvian)

* New translations validation.php (Latvian)

* New translations entities.php (Latvian)

* New translations activities.php (Polish)
2021-09-02 21:07:31 +01:00
Dan Brown
7028025380 Made the TOTP URL visible during setup
Useful for some non-scanner type apps.
Closes #2908
2021-09-01 20:58:19 +01:00
Dan Brown
ff494be952 Fixed lack of proper ordering of pages
Added test to cover
Fixes #2905
2021-09-01 20:30:02 +01:00
Dan Brown
9b226e7d39 Updated version and assets for release v21.08 2021-08-31 22:07:53 +01:00
Dan Brown
9865446267 Merge branch 'master' into release 2021-08-31 22:07:23 +01:00
Dan Brown
173f728e4a Updated translator attribution before release v21.08 2021-08-31 22:05:16 +01:00
Dan Brown
9772b2f69d Applied stylci changes 2021-08-31 22:03:51 +01:00
Dan Brown
c0f4cf4b5c Merge branch 'master' of github.com:BookStackApp/BookStack 2021-08-31 21:59:37 +01:00
Dan Brown
cc1f46cbf4 New Crowdin updates (#2893)
* New translations settings.php (Chinese Traditional)

* New translations settings.php (Indonesian)

* New translations settings.php (Swedish)

* New translations settings.php (Turkish)

* New translations settings.php (Ukrainian)

* New translations settings.php (Chinese Simplified)

* New translations settings.php (Vietnamese)

* New translations settings.php (Portuguese, Brazilian)

* New translations settings.php (Persian)

* New translations settings.php (Slovak)

* New translations settings.php (Spanish, Argentina)

* New translations settings.php (Croatian)

* New translations settings.php (Latvian)

* New translations settings.php (Bosnian)

* New translations settings.php (Norwegian Bokmal)

* New translations settings.php (German Informal)

* New translations settings.php (Slovenian)

* New translations settings.php (Russian)

* New translations settings.php (French)

* New translations settings.php (German)

* New translations settings.php (Spanish)

* New translations settings.php (Arabic)

* New translations settings.php (Bulgarian)

* New translations settings.php (Catalan)

* New translations settings.php (Czech)

* New translations settings.php (Danish)

* New translations settings.php (Hebrew)

* New translations settings.php (Portuguese)

* New translations settings.php (Hungarian)

* New translations settings.php (Italian)

* New translations settings.php (Japanese)

* New translations settings.php (Korean)

* New translations settings.php (Dutch)

* New translations settings.php (Polish)

* New translations settings.php (Lithuanian)

* New translations activities.php (German)

* New translations auth.php (German)

* New translations common.php (German)

* New translations settings.php (German)

* New translations validation.php (German)

* New translations settings.php (French)

* New translations validation.php (French)

* New translations activities.php (French)

* New translations auth.php (French)

* New translations common.php (French)

* New translations activities.php (Norwegian Bokmal)

* New translations auth.php (Norwegian Bokmal)

* New translations auth.php (Norwegian Bokmal)

* New translations common.php (Norwegian Bokmal)

* New translations settings.php (Norwegian Bokmal)

* New translations validation.php (Norwegian Bokmal)

* New translations auth.php (French)

* New translations entities.php (Chinese Traditional)

* New translations entities.php (Indonesian)

* New translations entities.php (Swedish)

* New translations entities.php (Turkish)

* New translations entities.php (Ukrainian)

* New translations entities.php (Chinese Simplified)

* New translations entities.php (Vietnamese)

* New translations entities.php (Portuguese, Brazilian)

* New translations entities.php (Persian)

* New translations entities.php (Slovak)

* New translations entities.php (Spanish, Argentina)

* New translations entities.php (Croatian)

* New translations entities.php (Latvian)

* New translations entities.php (Bosnian)

* New translations entities.php (Norwegian Bokmal)

* New translations entities.php (German Informal)

* New translations entities.php (Slovenian)

* New translations entities.php (Russian)

* New translations entities.php (French)

* New translations entities.php (German)

* New translations entities.php (Spanish)

* New translations entities.php (Arabic)

* New translations entities.php (Bulgarian)

* New translations entities.php (Catalan)

* New translations entities.php (Czech)

* New translations entities.php (Danish)

* New translations entities.php (Hebrew)

* New translations entities.php (Portuguese)

* New translations entities.php (Hungarian)

* New translations entities.php (Italian)

* New translations entities.php (Japanese)

* New translations entities.php (Korean)

* New translations entities.php (Dutch)

* New translations entities.php (Polish)

* New translations entities.php (Lithuanian)

* New translations entities.php (Spanish)

* New translations settings.php (Chinese Traditional)

* New translations settings.php (Indonesian)

* New translations settings.php (Swedish)

* New translations settings.php (Turkish)

* New translations settings.php (Ukrainian)

* New translations settings.php (Chinese Simplified)

* New translations settings.php (Vietnamese)

* New translations settings.php (Portuguese, Brazilian)

* New translations settings.php (Persian)

* New translations settings.php (Slovak)

* New translations settings.php (Spanish, Argentina)

* New translations settings.php (Croatian)

* New translations settings.php (Latvian)

* New translations settings.php (Bosnian)

* New translations settings.php (Norwegian Bokmal)

* New translations settings.php (German Informal)

* New translations settings.php (Slovenian)

* New translations settings.php (Russian)

* New translations settings.php (French)

* New translations settings.php (German)

* New translations settings.php (Spanish)

* New translations settings.php (Arabic)

* New translations settings.php (Bulgarian)

* New translations settings.php (Catalan)

* New translations settings.php (Czech)

* New translations settings.php (Danish)

* New translations settings.php (Hebrew)

* New translations settings.php (Portuguese)

* New translations settings.php (Hungarian)

* New translations settings.php (Italian)

* New translations settings.php (Japanese)

* New translations settings.php (Korean)

* New translations settings.php (Dutch)

* New translations settings.php (Polish)

* New translations settings.php (Lithuanian)

* New translations settings.php (Spanish)

* New translations activities.php (Persian)

* New translations auth.php (Persian)

* New translations activities.php (Chinese Simplified)

* New translations auth.php (Chinese Simplified)

* New translations activities.php (Chinese Simplified)

* New translations auth.php (Chinese Simplified)

* New translations common.php (Chinese Simplified)

* New translations settings.php (Chinese Simplified)

* New translations validation.php (Chinese Simplified)

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

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

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

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

* New translations entities.php (German Informal)

* New translations activities.php (Lithuanian)

* New translations settings.php (Lithuanian)

* New translations passwords.php (Lithuanian)

* New translations errors.php (Lithuanian)

* New translations entities.php (Lithuanian)

* New translations common.php (Lithuanian)

* New translations auth.php (Lithuanian)

* New translations validation.php (Spanish, Argentina)

* New translations settings.php (Spanish, Argentina)

* New translations common.php (Spanish, Argentina)

* New translations auth.php (Spanish, Argentina)

* New translations activities.php (Spanish, Argentina)

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

* New translations settings.php (Chinese Simplified)

* New translations common.php (Chinese Simplified)

* New translations entities.php (Chinese Simplified)

* New translations settings.php (Portuguese)

* New translations activities.php (Portuguese)

* New translations common.php (Portuguese)

* New translations entities.php (Portuguese)

* New translations settings.php (French)

* New translations entities.php (Latvian)

* New translations common.php (Latvian)

* New translations common.php (Italian)

* New translations settings.php (Italian)

* New translations entities.php (Italian)

* New translations entities.php (German)

* New translations entities.php (Dutch)

* New translations settings.php (German)

* New translations settings.php (Dutch)

* New translations common.php (German)

* New translations common.php (Dutch)

* New translations settings.php (Italian)

* New translations activities.php (Persian)

* New translations activities.php (Persian)

* New translations auth.php (Persian)

* New translations auth.php (Persian)

* New translations validation.php (Persian)

* New translations validation.php (Persian)

* New translations common.php (Persian)

* New translations pagination.php (Persian)

* New translations passwords.php (Persian)

* New translations common.php (Persian)

* New translations components.php (Persian)

* New translations errors.php (Persian)

* New translations errors.php (Persian)

* New translations entities.php (Persian)

* New translations activities.php (Norwegian Bokmal)

* New translations common.php (Norwegian Bokmal)

* New translations entities.php (Norwegian Bokmal)

* New translations errors.php (Norwegian Bokmal)

* New translations settings.php (Norwegian Bokmal)

* New translations settings.php (Norwegian Bokmal)

* New translations activities.php (Polish)

* New translations common.php (Polish)

* New translations errors.php (Polish)

* New translations settings.php (Polish)

* New translations activities.php (Czech)

* New translations activities.php (Czech)

* New translations auth.php (Czech)

* New translations common.php (Czech)

* New translations entities.php (Czech)

* New translations errors.php (Czech)

* New translations passwords.php (Czech)

* New translations auth.php (Czech)

* New translations entities.php (Czech)

* New translations settings.php (Czech)

* New translations validation.php (Czech)

* New translations auth.php (Czech)

* New translations auth.php (Czech)

* New translations entities.php (Czech)

* New translations settings.php (Czech)

* New translations components.php (Czech)

* New translations activities.php (Czech)

* New translations activities.php (Indonesian)

* New translations entities.php (Indonesian)

* New translations settings.php (Indonesian)

* New translations errors.php (Vietnamese)

* New translations common.php (Vietnamese)

* New translations activities.php (Chinese Traditional)

* New translations common.php (Chinese Traditional)

* New translations entities.php (Chinese Traditional)

* New translations errors.php (Chinese Traditional)

* New translations errors.php (Chinese Traditional)

* New translations settings.php (Chinese Traditional)

* New translations common.php (Portuguese, Brazilian)

* New translations common.php (Portuguese, Brazilian)

* New translations activities.php (Chinese Traditional)

* New translations common.php (Chinese Simplified)

* New translations activities.php (Ukrainian)

* New translations auth.php (Ukrainian)

* New translations common.php (Ukrainian)

* New translations settings.php (Ukrainian)

* New translations validation.php (Ukrainian)

* New translations activities.php (Chinese Simplified)

* New translations auth.php (Chinese Simplified)

* New translations settings.php (Chinese Simplified)

* New translations settings.php (Turkish)

* New translations validation.php (Chinese Simplified)

* New translations auth.php (Chinese Traditional)

* New translations validation.php (Chinese Traditional)

* New translations activities.php (Vietnamese)

* New translations auth.php (Vietnamese)

* New translations common.php (Vietnamese)

* New translations settings.php (Vietnamese)

* New translations validation.php (Vietnamese)

* New translations validation.php (Turkish)

* New translations common.php (Turkish)

* New translations auth.php (Portuguese, Brazilian)

* New translations auth.php (Slovenian)

* New translations validation.php (Russian)

* New translations activities.php (Slovak)

* New translations auth.php (Slovak)

* New translations common.php (Slovak)

* New translations settings.php (Slovak)

* New translations validation.php (Slovak)

* New translations activities.php (Slovenian)

* New translations common.php (Slovenian)

* New translations auth.php (Turkish)

* New translations settings.php (Slovenian)

* New translations validation.php (Slovenian)

* New translations activities.php (Swedish)

* New translations auth.php (Swedish)

* New translations common.php (Swedish)

* New translations settings.php (Swedish)

* New translations validation.php (Swedish)

* New translations activities.php (Turkish)

* New translations activities.php (Portuguese, Brazilian)

* New translations settings.php (Portuguese, Brazilian)

* New translations common.php (Russian)

* New translations validation.php (Bosnian)

* New translations common.php (Latvian)

* New translations settings.php (Latvian)

* New translations validation.php (Latvian)

* New translations activities.php (Bosnian)

* New translations auth.php (Bosnian)

* New translations common.php (Bosnian)

* New translations settings.php (Bosnian)

* New translations activities.php (Norwegian Bokmal)

* New translations activities.php (Latvian)

* New translations auth.php (Norwegian Bokmal)

* New translations common.php (Norwegian Bokmal)

* New translations settings.php (Norwegian Bokmal)

* New translations validation.php (Norwegian Bokmal)

* New translations activities.php (German Informal)

* New translations auth.php (German Informal)

* New translations common.php (German Informal)

* New translations settings.php (German Informal)

* New translations auth.php (Latvian)

* New translations validation.php (Croatian)

* New translations validation.php (Portuguese, Brazilian)

* New translations settings.php (Persian)

* New translations activities.php (Indonesian)

* New translations auth.php (Indonesian)

* New translations common.php (Indonesian)

* New translations settings.php (Indonesian)

* New translations validation.php (Indonesian)

* New translations activities.php (Persian)

* New translations auth.php (Persian)

* New translations common.php (Persian)

* New translations validation.php (Persian)

* New translations settings.php (Croatian)

* New translations activities.php (Spanish, Argentina)

* New translations auth.php (Spanish, Argentina)

* New translations common.php (Spanish, Argentina)

* New translations settings.php (Spanish, Argentina)

* New translations validation.php (Spanish, Argentina)

* New translations activities.php (Croatian)

* New translations auth.php (Croatian)

* New translations common.php (Croatian)

* New translations settings.php (Russian)

* New translations auth.php (Russian)

* New translations common.php (Chinese Traditional)

* New translations common.php (Czech)

* New translations validation.php (Bulgarian)

* New translations activities.php (Catalan)

* New translations auth.php (Catalan)

* New translations common.php (Catalan)

* New translations settings.php (Catalan)

* New translations validation.php (Catalan)

* New translations auth.php (Czech)

* New translations settings.php (Czech)

* New translations common.php (Bulgarian)

* New translations validation.php (Czech)

* New translations activities.php (Danish)

* New translations auth.php (Danish)

* New translations common.php (Danish)

* New translations settings.php (Danish)

* New translations validation.php (Danish)

* New translations activities.php (German)

* New translations auth.php (German)

* New translations settings.php (Bulgarian)

* New translations auth.php (Bulgarian)

* New translations settings.php (German)

* New translations activities.php (Spanish)

* New translations settings.php (Chinese Traditional)

* New translations common.php (Portuguese, Brazilian)

* New translations activities.php (Czech)

* New translations activities.php (French)

* New translations auth.php (French)

* New translations common.php (French)

* New translations settings.php (French)

* New translations validation.php (French)

* New translations auth.php (Spanish)

* New translations activities.php (Bulgarian)

* New translations common.php (Spanish)

* New translations settings.php (Spanish)

* New translations validation.php (Spanish)

* New translations activities.php (Arabic)

* New translations auth.php (Arabic)

* New translations common.php (Arabic)

* New translations settings.php (Arabic)

* New translations validation.php (Arabic)

* New translations common.php (German)

* New translations validation.php (German)

* New translations activities.php (Russian)

* New translations activities.php (Polish)

* New translations settings.php (Korean)

* New translations validation.php (Korean)

* New translations activities.php (Dutch)

* New translations auth.php (Dutch)

* New translations common.php (Dutch)

* New translations settings.php (Dutch)

* New translations validation.php (Dutch)

* New translations auth.php (Polish)

* New translations auth.php (Korean)

* New translations common.php (Polish)

* New translations settings.php (Polish)

* New translations validation.php (Polish)

* New translations activities.php (Portuguese)

* New translations auth.php (Portuguese)

* New translations common.php (Portuguese)

* New translations settings.php (Portuguese)

* New translations validation.php (Portuguese)

* New translations common.php (Korean)

* New translations activities.php (Korean)

* New translations activities.php (Hebrew)

* New translations validation.php (Hungarian)

* New translations auth.php (Hebrew)

* New translations common.php (Hebrew)

* New translations settings.php (Hebrew)

* New translations validation.php (Hebrew)

* New translations activities.php (Hungarian)

* New translations auth.php (Hungarian)

* New translations common.php (Hungarian)

* New translations settings.php (Hungarian)

* New translations activities.php (Italian)

* New translations validation.php (Japanese)

* New translations auth.php (Italian)

* New translations common.php (Italian)

* New translations settings.php (Italian)

* New translations validation.php (Italian)

* New translations activities.php (Japanese)

* New translations auth.php (Japanese)

* New translations common.php (Japanese)

* New translations settings.php (Japanese)

* New translations validation.php (German Informal)

* New translations activities.php (Spanish)

* New translations auth.php (Spanish)

* New translations common.php (Spanish)

* New translations settings.php (Spanish)

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

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

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

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

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

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

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

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

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

* New translations entities.php (Indonesian)

* New translations errors.php (Indonesian)

* New translations auth.php (Chinese Simplified)

* New translations auth.php (Chinese Simplified)

* New translations errors.php (Indonesian)

* New translations entities.php (Indonesian)

* New translations errors.php (Indonesian)

* New translations settings.php (Indonesian)

* New translations validation.php (Indonesian)

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

For #2804
2021-06-13 12:53:04 +01:00
Dan Brown
7997300f96 Added front-end toggle and testing of inline attachments 2021-06-06 13:55:56 +01:00
Dan Brown
888f435651 Added back-end attachments-in-browser support
A query string will cause attachments to be provided inline
with an appropriate mime type.
Remaining actions:
- Tests
- Front-end functionality
- Config option?
2021-06-06 00:51:06 +01:00
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
Alireza Arjvand
2744b2a243 Added parent info to recycle bin 2021-04-17 13:09:56 +04:30
James Geiger
a0bfdf0e5c Code cleanup, bug squashing 2021-02-09 01:27:27 -06:00
James Geiger
7ef17bb394 PageContent return null issue 2021-02-09 00:21:07 -06:00
James Geiger
48587d2c38 Code cleanup, refactor
Updated to use Str::length for entity descriptions.
Moved function to get first image in page to PageContent class.
2021-02-09 00:16:24 -06:00
James Geiger
e458411f91 Create Open Graph meta tags for book/page/chapter/shelf 2020-12-21 23:20:13 -06:00
James Geiger
4b36df08a8 Merge pull request #1 from BookStackApp/master
Update from base/master
2020-12-03 11:39:06 -06:00
Jasper Weyne
69a47319d5 Default OpenID display name set to standard value 2020-08-05 13:14:46 +02:00
Jasper Weyne
35c48b9416 Method descriptions 2020-08-05 00:18:43 +02:00
Jasper Weyne
f2d320825a Simplify refresh method 2020-08-04 22:09:53 +02:00
Jasper Weyne
23402ae812 Initial unit tests for OpenID 2020-08-04 21:30:17 +02:00
Jasper Weyne
6feaf25c90 Increase robustness of the refresh method 2020-08-04 21:29:11 +02:00
Jasper Weyne
46388a591b AccessToken empty array parameter on null 2020-07-09 18:29:44 +02:00
Jasper Weyne
75b4a05200 Add OpenIdService to OpenIdSessionGuard constructor call 2020-07-09 18:00:16 +02:00
Jasper Weyne
13d0260cc9 Configurable OpenID Connect services 2020-07-09 16:27:45 +02:00
Jasper Weyne
97cde9c56a Generalize refresh failure handling 2020-07-08 17:02:52 +02:00
Jasper Weyne
5df7db5105 Ignore ID token expiry if unavailable 2020-07-07 02:51:33 +02:00
Jasper Weyne
10c890947f Token expiration and refreshing using the refresh_token flow 2020-07-07 02:26:00 +02:00
Jasper Weyne
25144a13c7 Deduplicated getOrRegisterUser method 2020-07-06 18:14:43 +02:00
Jasper Weyne
07a6d7655f First basic OpenID Connect implementation 2020-07-01 23:27:50 +02:00
Nikhil Jha
e287d965f5 move zip export into exportservice 2020-05-13 20:07:19 -07:00
Nikhil Jha
ea82c2f61b support exporting books as zip files 2020-05-13 19:57:59 -07:00
Nikhil Jha
a7d9646b19 support exporting WYSIWYG pages as Markdown 2020-05-13 18:34:22 -07:00
Nikhil Jha
a34a07c610 basic markdown export 2020-05-12 21:12:26 -07:00
3033 changed files with 264269 additions and 85162 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
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
@@ -32,38 +36,58 @@ APP_LANG=en
# APP_LANG will be used if such a header is not provided.
APP_AUTO_LANG_PUBLIC=true
# Application timezone
# Used where dates are displayed such as on exported content.
# Application timezones
# The first option is used to determine what timezone is used for date storage.
# Leaving that as "UTC" is advised.
# The second option is used to set the timezone which will be used for date
# formatting and display. This defaults to the "APP_TIMEZONE" value.
# Valid timezone values can be found here: https://www.php.net/manual/en/timezones.php
APP_TIMEZONE=UTC
APP_DISPLAY_TIMEZONE=UTC
# Application theme
# Used to specific a themes/<APP_THEME> folder where BookStack UI
# overrides can be made. Defaults to disabled.
APP_THEME=false
# 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.
# Set to an IP address, or multiple comma seperated IP addresses.
# Can alternatively be set to "*" to trust all proxy addresses.
APP_PROXIES=null
# Database details
# Host can contain a port (localhost:3306) or a separate DB_PORT option can be used.
# An ipv6 address can be used via the square bracket format ([::1]).
DB_HOST=localhost
DB_PORT=3306
DB_DATABASE=database_database
DB_USERNAME=database_username
DB_PASSWORD=database_user_password
# Mail system to use
# Can be 'smtp' or 'sendmail'
MAIL_DRIVER=smtp
# 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_FROM=mail@bookstackapp.com
# Mail configuration
# Refer to https://www.bookstackapp.com/docs/admin/email-webhooks/#email-configuration
MAIL_DRIVER=smtp
MAIL_FROM=bookstack@example.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'
@@ -92,8 +116,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
@@ -126,9 +149,13 @@ STORAGE_S3_ENDPOINT=https://my-custom-s3-compatible.service.com:8001
STORAGE_URL=false
# Authentication method to use
# Can be 'standard', 'ldap' or 'saml2'
# 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/
@@ -193,10 +220,11 @@ LDAP_SERVER=false
LDAP_BASE_DN=false
LDAP_DN=false
LDAP_PASS=false
LDAP_USER_FILTER=false
LDAP_USER_FILTER="(&(uid={user}))"
LDAP_VERSION=false
LDAP_START_TLS=false
LDAP_TLS_INSECURE=false
LDAP_TLS_CA_CERT=false
LDAP_ID_ATTRIBUTE=uid
LDAP_EMAIL_ATTRIBUTE=mail
LDAP_DISPLAY_NAME_ATTRIBUTE=cn
@@ -209,6 +237,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/
@@ -224,6 +253,8 @@ SAML2_ONELOGIN_OVERRIDES=null
SAML2_DUMP_USER_DETAILS=false
SAML2_AUTOLOAD_METADATA=false
SAML2_IDP_AUTHNCONTEXT=true
SAML2_SP_x509=null
SAML2_SP_x509_KEY=null
# SAML group sync configuration
# Refer to https://www.bookstackapp.com/docs/admin/saml2-auth/
@@ -231,6 +262,26 @@ SAML2_USER_TO_GROUPS=false
SAML2_GROUP_ATTRIBUTE=group
SAML2_REMOVE_FROM_GROUPS=false
# OpenID Connect authentication configuration
# Refer to https://www.bookstackapp.com/docs/admin/oidc-auth/
OIDC_NAME=SSO
OIDC_DISPLAY_NAME_CLAIMS=name
OIDC_CLIENT_ID=null
OIDC_CLIENT_SECRET=null
OIDC_ISSUER=null
OIDC_ISSUER_DISCOVER=false
OIDC_PUBLIC_KEY=null
OIDC_AUTH_ENDPOINT=null
OIDC_TOKEN_ENDPOINT=null
OIDC_USERINFO_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
OIDC_END_SESSION_ENDPOINT=false
# Disable default third-party services such as Gravatar and Draw.IO
# Service-specific options will override this option
DISABLE_EXTERNAL_SERVICES=false
@@ -244,7 +295,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
@@ -261,7 +312,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
@@ -271,6 +322,35 @@ REVISION_LIMIT=50
# Set to -1 for unlimited recycle bin lifetime.
RECYCLE_BIN_LIFETIME=30
# File Upload Limit
# 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
# Export PDF Command
# Set a command which can be used to convert a HTML file into a PDF file.
# When false this will not be used.
# String values represent the command to be called for conversion.
# Supports '{input_html_path}' and '{output_pdf_path}' placeholder values.
# Example: EXPORT_PDF_COMMAND="/scripts/convert.sh {input_html_path} {output_pdf_path}"
EXPORT_PDF_COMMAND=false
# Export PDF Command Timeout
# The number of seconds that the export PDF command will run before a timeout occurs.
# Only applies for the EXPORT_PDF_COMMAND option, not for DomPDF or wkhtmltopdf.
EXPORT_PDF_COMMAND_TIMEOUT=15
# 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
@@ -281,12 +361,34 @@ ALLOW_CONTENT_SCRIPTS=false
# Contents of the robots.txt file can be overridden, making this option obsolete.
ALLOW_ROBOTS=null
# Allow server-side fetches to be performed to potentially unknown
# and user-provided locations. Primarily used in exports when loading
# in externally referenced assets.
# Can be 'true' or 'false'.
ALLOW_UNTRUSTED_SERVER_FETCHING=false
# A list of hosts that BookStack can be iframed within.
# Space separated if multiple. BookStack host domain is auto-inferred.
# For Example: ALLOWED_IFRAME_HOSTS="https://example.com https://a.example.com"
# Setting this option will also auto-adjust cookies to be SameSite=None.
ALLOWED_IFRAME_HOSTS=null
# 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
@@ -301,3 +403,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,17 +0,0 @@
---
name: New API Endpoint or Feature
about: Request a new endpoint or API feature be added
labels: ":nut_and_bolt: API Request"
---
#### API Endpoint or Feature
Clearly describe what you'd like to have added to the API.
#### Use-Case
Explain the use-case that you're working-on that requires the above request.
#### Additional Context
If required, add any other context about the feature request here.

25
.github/ISSUE_TEMPLATE/api_request.yml vendored Normal file
View File

@@ -0,0 +1,25 @@
name: New API Endpoint or API Ability
description: Request a new endpoint or API feature be added
labels: [":nut_and_bolt: API Request"]
body:
- type: textarea
id: feature
attributes:
label: API Endpoint or Feature
description: Clearly describe what you'd like to have added to the API.
validations:
required: true
- type: textarea
id: usecase
attributes:
label: Use-Case
description: Explain the use-case that you're working-on that requires the above request.
validations:
required: true
- type: textarea
id: context
attributes:
label: Additional context
description: Add any other context about the feature request here.
validations:
required: false

View File

@@ -1,29 +0,0 @@
---
name: Bug Report
about: Create a report to help us improve
---
**Describe the bug**
A clear and concise description of what the bug is.
**Steps To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Your Configuration (please complete the following information):**
- Exact BookStack Version (Found in settings):
- PHP Version:
- Hosting Method (Nginx/Apache/Docker):
**Additional context**
Add any other context about the problem here.

61
.github/ISSUE_TEMPLATE/bug_report.yml vendored Normal file
View File

@@ -0,0 +1,61 @@
name: Bug Report
description: Create a report to help us fix bugs & issues in existing supported functionality
labels: [":bug: Bug"]
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to fill out a bug report!
Please note that this form is for reporting bugs in existing supported functionality.
If you are reporting something that's not an issue in functionality we've previously supported and/or is simply something different to your expectations, then it may be more appropriate to raise via a feature or support request instead.
- type: textarea
id: description
attributes:
label: Describe the Bug
description: Provide a clear and concise description of what the bug is.
validations:
required: true
- type: textarea
id: reproduction
attributes:
label: Steps to Reproduce
description: Detail the steps that would replicate this issue.
placeholder: |
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
validations:
required: true
- type: textarea
id: expected
attributes:
label: Expected Behaviour
description: Provide clear and concise description of what you expected to happen.
validations:
required: true
- type: textarea
id: context
attributes:
label: Screenshots or Additional Context
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:
label: Exact BookStack Version
description: This can be found in the settings view of BookStack. Please provide an exact version(s) you've tested on.
placeholder: (eg. v23.06.7)
validations:
required: true

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,14 +0,0 @@
---
name: Feature Request
about: Suggest an idea for this project
---
**Describe the feature you'd like**
A clear description of the feature you'd like implemented in BookStack.
**Describe the benefits this feature would bring to BookStack users**
Explain the measurable benefits this feature would achieve.
**Additional context**
Add any other context or screenshots about the feature request here.

View File

@@ -0,0 +1,58 @@
name: Feature Request
description: Request a new feature or idea to be added to BookStack
labels: [":hammer: Feature Request"]
body:
- type: textarea
id: description
attributes:
label: Describe the feature you'd like
description: Provide a clear description of the feature you'd like implemented in BookStack
validations:
required: true
- type: textarea
id: benefits
attributes:
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 fundamental benefit/goal of your request.
options:
- label: I have searched for existing issues and none cover my fundamental request
required: true
- type: dropdown
id: existing_usage
attributes:
label: How long have you been using BookStack?
options:
- Not using yet, just scoping
- Under 3 months
- 3 months to 1 year
- 1 to 5 years
- Over 5 years
validations:
required: true
- type: textarea
id: context
attributes:
label: Additional context
description: Add any other context or screenshots about the feature request here.
validations:
required: false

View File

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

View File

@@ -0,0 +1,31 @@
name: Language Request
description: Request a new language to be added to Crowdin for you to translate
labels: [":earth_africa: Translations"]
assignees:
- ssddanbrown
body:
- type: markdown
attributes:
value: |
Thanks for offering to help start a new translation for BookStack!
- type: input
id: language
attributes:
label: Language to Add
description: What language (and region if applicable) are you offering to help add to BookStack?
validations:
required: true
- type: checkboxes
id: confirm
attributes:
label: Confirmation of Intent
description: |
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.
required: true
- type: markdown
attributes:
value: |
*__Note: New languages are added at specific points of the development process so it may be a small while before the requested language is added for translation.__*

View File

@@ -0,0 +1,55 @@
name: Support Request
description: Request support for a specific problem you have not been able to solve yourself
labels: [":dog2: Support"]
body:
- type: checkboxes
id: useddocs
attributes:
label: Attempted Debugging
description: |
I have read the [BookStack debugging](https://www.bookstackapp.com/docs/admin/debugging/) page and seeked resolution or more
detail for the issue.
options:
- label: I have read the debugging page
required: true
- type: checkboxes
id: searchissue
attributes:
label: Searched GitHub Issues
description: |
I have searched for the issue and potential resolutions within the [project's GitHub issue list](https://github.com/BookStackApp/BookStack/issues)
options:
- label: I have searched GitHub for the issue.
required: true
- type: textarea
id: scenario
attributes:
label: Describe the Scenario
description: Detail the problem that you're having or what you need support with.
validations:
required: true
- type: input
id: bsversion
attributes:
label: Exact BookStack Version
description: This can be found in the settings view of BookStack. Please provide an exact version.
placeholder: (eg. v23.06.7)
validations:
required: true
- type: textarea
id: logs
attributes:
label: Log Content
description: If the issue has produced an error, provide any [BookStack or server log](https://www.bookstackapp.com/docs/admin/debugging/) content below.
placeholder: Be sure to remove any confidential details in your logs
render: text
validations:
required: false
- type: textarea
id: hosting
attributes:
label: Hosting Environment
description: Describe your hosting environment as much as possible including any proxies used (If applicable).
placeholder: (eg. PHP8.1 on Ubuntu 22.04 VPS, installed using official installation script)
validations:
required: true

View File

@@ -0,0 +1,9 @@
name: Blank Request (Maintainers Only)
description: For maintainers only - Start a blank request
body:
- type: markdown
attributes:
value: "**This blank request option is only for existing official maintainers of the project!** Please instead use a different request option. If you use this your issue will be closed off."
- type: textarea
attributes:
label: Description

27
.github/SECURITY.md vendored Normal file
View File

@@ -0,0 +1,27 @@
# Security Policy
## Supported Versions
Only the [latest version](https://github.com/BookStackApp/BookStack/releases) of BookStack is supported.
We generally don't support older versions of BookStack due to maintenance effort and
since we aim to provide a fairly stable upgrade path for new versions.
## Security Notifications
If you'd like to be notified of new potential security concerns you can [sign-up to the BookStack security mailing list](https://updates.bookstackapp.com/signup/bookstack-security-updates).
## Reporting a Vulnerability
If you've found an issue that likely has no impact to existing users (For example, in a development-only branch)
feel free to raise it via a standard GitHub bug report issue.
If the issue could have a security impact to BookStack instances,
please directly contact the lead maintainer [@ssddanbrown](https://github.com/ssddanbrown).
You will need to log in to be able to see the email address on the [GitHub profile page](https://github.com/ssddanbrown).
Alternatively you can send a DM via Mastodon to [@danb@fosstodon.org](https://fosstodon.org/@danb).
Please be patient while the vulnerability is being reviewed. Deploying the fix to address the vulnerability
can often take a little time due to the amount of preparation required, to ensure the vulnerability has
been covered, and to create the content required to adequately notify the user-base.
Thank you for keeping BookStack instances safe!

View File

@@ -55,6 +55,9 @@ Name :: Languages
@Baptistou :: French
@arcoai :: Spanish
@Jokuna :: Korean
@smartshogu :: German; German Informal
@samadha56 :: Persian
@mrmuminov :: Uzbek
cipi1965 :: Italian
Mykola Ronik (Mantikor) :: Ukrainian
furkanoyk :: Turkish
@@ -126,7 +129,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,9 +139,9 @@ 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
Zero Huang (johnroyer) :: Chinese Traditional
jackaaa :: Chinese Traditional
Irfan Hukama Arsyad (IrfanArsyad) :: Indonesian
Jeff Huang (s8321414) :: Chinese Traditional
@@ -158,12 +161,353 @@ 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
fharis arabia (raednahdi) :: Arabic
Alexander Predl (Harveyhase68) :: German
Rem (Rem9000) :: Dutch
Michał Stelmach (stelmach-web) :: Polish
arniom :: French
REMOVED_USER :: French; German; Dutch; Portuguese, Brazilian; Portuguese; Turkish;
林祖年 (contagion) :: Chinese Traditional
Siamak Guodarzi (siamakgoudarzi88) :: Persian
Lis Maestrelo (lismtrl) :: Portuguese, Brazilian
Nathanaël (nathanaelhoun) :: French
A Ibnu Hibban (abd.ibnuhibban) :: Indonesian
Frost-ZX :: Chinese Simplified
Kuzma Simonov (ovmach) :: Russian
Vojtěch Krystek (acantophis) :: Czech
Michał Lipok (mLipok) :: Polish
Nicolas Pawlak (Mikolajek) :: French; Polish; German
Thomas Hansen (thomasdk81) :: Danish
Hl2run :: Slovak
Ngo Tri Hoai (trihoai) :: Vietnamese
Atalonica :: Catalan
慕容潭谈 (591442386) :: Chinese Simplified
Radim Pesek (ramess18) :: Czech
anastasiia.motylko :: Ukrainian
Indrek Haav (IndrekHaav) :: Estonian
na3shkw :: Japanese
Giancarlo Di Massa (digitall-it) :: Italian
M Nafis Al Mukhdi (mnafisalmukhdi1) :: Indonesian
sulfo :: Danish
Raukze :: German
zygimantus :: Lithuanian
marinkaberg :: Russian
Vitaliy (gviabcua) :: Ukrainian
mannycarreiro :: Portuguese
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
Jakob Åsell (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
Jihyeon 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 Informal; German
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
Hsin-Hsiang 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; German Informal
Guttorm Hveem (guttormhveem) :: Norwegian Nynorsk; 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
TWME :: Chinese Traditional
Sascha (Man-in-Black) :: German; German Informal
Mohammadreza Madadi (madadi.efl) :: Persian
Konstantin (kkovacheli) :: Ukrainian; Russian
link1183 :: French
Renan (rfpe) :: Portuguese, Brazilian
Lowkey (bbsweb) :: Chinese Simplified
ZZnOB (zznobzz) :: Russian
rupus :: Swedish
developernecsys :: Norwegian Nynorsk
xuan LI (xuanli233) :: Chinese Simplified
LameeQS :: Latvian
Sorin T. (trimbitassorin) :: Romanian
poesty :: Chinese Simplified
balmag :: Hungarian
Antti-Jussi Nygård (ajnyga) :: Finnish
Eduard Ereza Martínez (Ereza) :: Catalan
Jabir Lang (amar.almrad) :: Arabic
Jaroslav Kobližek (foretix) :: Czech; French
Wiktor Adamczyk (adamczyk.wiktor) :: Polish
Abdulmajeed Alshuaibi (4Majeed) :: Arabic
NotSmartZakk :: Czech
HyoungMin Lee (ddokkaebi) :: Korean
Dasferco :: Chinese Simplified
Marcus Teräs (mteras) :: Finnish
Serkan Yardim (serkanzz) :: Turkish
Y (cnsr) :: Ukrainian
ZY ZV (vy0b0x) :: Chinese Simplified
diegobenitez :: Spanish
Marc Hagen (MarcHagen) :: Dutch
Kasper Alsøe (zeonos) :: Danish
sultani :: Persian
renge :: Korean
Tim (thegatesdev) :: Dutch; German Informal; French; Romanian; Catalan; Czech; Danish; German; Finnish; Hungarian; Italian; Japanese; Korean; Polish; Russian; Ukrainian; Chinese Simplified; Chinese Traditional; Portuguese, Brazilian; Persian; Spanish, Argentina; Croatian; Norwegian Nynorsk; Estonian; Uzbek; Norwegian Bokmal
Irdi (irdiOL) :: Albanian
KateBarber :: Welsh
Twister (theuncles75) :: Hebrew
algernon19 :: Hungarian
Ivan Krstic (ikrstic) :: Serbian (Cyrillic)
Show :: Russian
xBahamut :: Portuguese, Brazilian
Pavle Knežević (pavleknezzevic) :: Serbian (Cyrillic)
Vanja Cvelbar (b100w11) :: Slovenian
simonpct :: French
Honza Nagy (honza.nagy) :: Czech
asd20752 :: Norwegian Bokmal
Jan Picka (polipones) :: Czech
diogoalex991 :: Portuguese
Ehsan Sadeghi (ehsansadeghi) :: Persian
ka_picit :: Danish
cracrayol :: French
CapuaSC :: Dutch
Guardian75 :: German Informal
mr-kanister :: German
Michele Bastianelli (makoblaster) :: Italian
jespernissen :: Danish
Andrey (avmaksimov) :: Russian
Gonzalo Loyola (AlFcl) :: Spanish, Argentina; Spanish
grobert63 :: French
wusst. (Supporti) :: German
MaximMaximS :: Czech
damian-klima :: Slovak
crow_ :: Latvian
JocelynDelalande :: French
Jan (JW-CH) :: German Informal
Timo B (lommes) :: German Informal
Erik Lundstedt (Erik.Lundstedt) :: Swedish
yngams (younessmouhid) :: Arabic
Ohadp :: Hebrew
cbridi :: Portuguese, Brazilian
nanangsb :: Indonesian
Michal Melich (michalmelich) :: Czech
David (david-prv) :: German; German Informal
Larry (lahoje) :: Swedish
Marcia dos Santos (marciab80) :: Portuguese
Ricard López Torres (richilpez.torres) :: Catalan
sarahalves7 :: Portuguese, Brazilian
petr.husak :: Czech
javadataherian :: Persian
Ludo-code :: French
hollsten :: Swedish
Ngoc Lan Phung (lanpncz) :: Vietnamese
Worive :: Catalan; French
Илья Скаба (skabailya) :: Russian
Irjan Olsen (Irch) :: Norwegian Bokmal
Aleksandar Jovanovic (jovanoviczaleksandar) :: Serbian (Cyrillic)
Red (RedVortex) :: Hebrew
xgrug :: Chinese Simplified
HrCalmar :: Danish
Avishay Rapp (AvishayRapp) :: Hebrew
matthias4217 :: French
Berke BOYLU2 (berkeboylu2) :: Turkish
etwas7B :: German
Mohammed srhiri (m.sghiri20) :: Arabic
YongMin Kim (kym0118) :: Korean
Rivo Zängov (Eraser) :: Estonian
Francisco Rafael Fonseca (chicoraf) :: Portuguese, Brazilian
ИEØ_ΙΙØZ (NEO_IIOZ) :: Chinese Traditional
madnjpn (madnjpn.) :: Georgian
Ásgeir Shiny Ásgeirsson (AsgeirShiny) :: Icelandic
Mohammad Aftab Uddin (chirohorit) :: Bengali
Yannis Karlaftis (meliseus) :: Greek
felixxx :: German Informal
randi (randi65535) :: Korean
test65428 :: Greek
zeronell :: Chinese Simplified
julien Vinber (julienVinber) :: French
Hyunwoo Park (oksure) :: Korean
aram.rafeq.7 (aramrafeq2) :: Kurdish
Raphael Moreno (RaphaelMoreno) :: Portuguese, Brazilian
yn (user99) :: Arabic
Pavel Zlatarov (pzlatarov) :: Bulgarian
ingelres :: French
mabdullah :: Arabic
Skrabák Csaba (kekcsi) :: Hungarian
Evert Meulie (Evert) :: Norwegian Bokmal
Jasper Backer (jasperb) :: Dutch
Alexandar Cavdarovski (ace.200112) :: Swedish
구닥다리TV (yjj8353) :: Korean
Onur Oskay (o.oskay) :: Turkish
Sébastien Merveille (SebastienMerv) :: French
Maxim Kouznetsov (masya.work) :: Hebrew
neodvisnost :: Slovenian
Soubi Agatsuma (bisouya) :: Hebrew
Ilya Shaulov (ishaulov) :: Russian
Konstantin Bobkov (b.konstantv) :: Russian
Ruben Sutter (rubensutter) :: German
jellium :: French
Qxlkdr :: Swedish
Hari (muhhari) :: Indonesian
仙君御 (xjy) :: Chinese Simplified
TapioM :: Finnish
lingb58 :: Chinese Traditional
Angel Pandey (angel-pandey) :: Nepali
Supriya Shrestha (supriyashrestha) :: Nepali
gprabhat :: Nepali
CellCat :: Chinese Simplified
Al Desrahim (aldesrahim) :: Indonesian
ahmad abbaspour (deshneh.dar.diss) :: Persian
Erjon K. (ekr) :: Albanian
LiZerui (iamzrli) :: Chinese Traditional
Ticker (ticker.com) :: Hebrew
CrazyComputer :: Chinese Simplified
Firr (FirrV) :: Russian
João Faro (FaroJoaoFaro) :: Portuguese
Danilo dos Santos Barbosa (bozochegou) :: Portuguese, Brazilian
Chris (furesoft) :: German
Silvia Isern (eiendragon) :: Catalan
Dennis Kron Pedersen (ahjdp) :: Danish
iamwhoiamwhoami :: Swedish
Grogui :: French
MrCharlesIII :: Arabic
David Olsen (dawin) :: Danish
ltnzr :: French
Frank Holler (holler.frank) :: German; German Informal

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

@@ -0,0 +1,40 @@
name: analyse-php
on:
push:
paths:
- '**.php'
pull_request:
paths:
- '**.php'
jobs:
build:
if: ${{ github.ref != 'refs/heads/l10n_development' }}
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: 8.3
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@v4
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-8.3
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

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

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

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

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

View File

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

29
.github/workflows/test-js.yml vendored Normal file
View File

@@ -0,0 +1,29 @@
name: test-js
on:
push:
paths:
- '**.js'
- '**.ts'
- '**.json'
pull_request:
paths:
- '**.js'
- '**.ts'
- '**.json'
jobs:
build:
if: ${{ github.ref != 'refs/heads/l10n_development' }}
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- name: Install NPM deps
run: npm ci
- name: Run TypeScript type checking
run: npm run ts:lint
- name: Run JavaScript tests
run: npm run test

View File

@@ -2,27 +2,26 @@ name: test-migrations
on:
push:
branches:
- master
- release
- gh_actions_update
paths:
- '**.php'
- 'composer.*'
pull_request:
branches:
- '*'
- '*/*'
- '!l10n_master'
paths:
- '**.php'
- 'composer.*'
jobs:
build:
runs-on: ubuntu-20.04
if: ${{ github.ref != 'refs/heads/l10n_development' }}
runs-on: ubuntu-24.04
strategy:
matrix:
php: ['7.3', '7.4', '8.0']
php: ['8.2', '8.3', '8.4']
steps:
- uses: actions/checkout@v1
- uses: actions/checkout@v4
- name: Setup PHP
uses: shivammathur/setup-php@b7d1d9c9a92d8d8463ce36d7f60da34d461724f8
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
extensions: gd, mbstring, json, curl, xml, mysql, ldap
@@ -30,17 +29,18 @@ 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@v4
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ matrix.php }}
restore-keys: ${{ runner.os }}-composer-
- name: Start MySQL
run: |
sudo /etc/init.d/mysql start
sudo systemctl start mysql
- name: Create database & user
run: |

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

@@ -0,0 +1,61 @@
name: test-php
on:
push:
paths:
- '**.php'
- 'composer.*'
pull_request:
paths:
- '**.php'
- 'composer.*'
jobs:
build:
if: ${{ github.ref != 'refs/heads/l10n_development' }}
runs-on: ubuntu-24.04
strategy:
matrix:
php: ['8.2', '8.3', '8.4']
steps:
- uses: actions/checkout@v4
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
extensions: gd, mbstring, json, curl, xml, mysql, ldap, gmp
- 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@v4
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ matrix.php }}
restore-keys: ${{ runner.os }}-composer-
- name: Start Database
run: |
sudo systemctl start mysql
- name: Setup Database
run: |
mysql -uroot -proot -e 'CREATE DATABASE IF NOT EXISTS `bookstack-test`;'
mysql -uroot -proot -e "CREATE USER 'bookstack-test'@'localhost' IDENTIFIED WITH mysql_native_password BY 'bookstack-test';"
mysql -uroot -proot -e "GRANT ALL ON \`bookstack-test\`.* TO 'bookstack-test'@'localhost';"
mysql -uroot -proot -e 'FLUSH PRIVILEGES;'
- name: Install composer dependencies
run: composer install --prefer-dist --no-interaction --ansi
- name: Migrate and seed the database
run: |
php${{ matrix.php }} artisan migrate --force -n --database=mysql_testing
php${{ matrix.php }} artisan db:seed --force -n --class=DummyContentSeeder --database=mysql_testing
- name: Run PHP tests
run: php${{ matrix.php }} ./vendor/bin/phpunit

11
.gitignore vendored
View File

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

View File

@@ -1,7 +1,6 @@
The MIT License (MIT)
Copyright (c) 2020 Dan Brown and the BookStack Project contributors
https://github.com/BookStackApp/BookStack/graphs/contributors
Copyright (c) 2015-2025, 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

@@ -0,0 +1,121 @@
<?php
namespace BookStack\Access\Controllers;
use BookStack\Access\EmailConfirmationService;
use BookStack\Access\LoginService;
use BookStack\Exceptions\ConfirmationEmailException;
use BookStack\Exceptions\UserTokenExpiredException;
use BookStack\Exceptions\UserTokenNotFoundException;
use BookStack\Http\Controller;
use BookStack\Users\UserRepo;
use Exception;
use Illuminate\Http\Request;
class ConfirmEmailController extends Controller
{
public function __construct(
protected EmailConfirmationService $emailConfirmationService,
protected LoginService $loginService,
protected UserRepo $userRepo
) {
}
/**
* Show the page to tell the user to check their email
* and confirm their address.
*/
public function show()
{
return view('auth.register-confirm');
}
/**
* Shows a notice that a user's email address has not been confirmed,
* along with the option to re-send the confirmation email.
*/
public function showAwaiting()
{
$user = $this->loginService->getLastLoginAttemptUser();
if ($user === null) {
$this->showErrorNotification(trans('errors.login_user_not_found'));
return redirect('/login');
}
return view('auth.register-confirm-awaiting');
}
/**
* 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(Request $request)
{
$validated = $this->validate($request, [
'token' => ['required', 'string']
]);
$token = $validated['token'];
try {
$userId = $this->emailConfirmationService->checkTokenAndGetUserId($token);
} catch (UserTokenNotFoundException $exception) {
$this->showErrorNotification(trans('errors.email_confirmation_invalid'));
return redirect('/register');
} catch (UserTokenExpiredException $exception) {
$user = $this->userRepo->getById($exception->userId);
$this->emailConfirmationService->sendConfirmation($user);
$this->showErrorNotification(trans('errors.email_confirmation_expired'));
return redirect('/register/confirm');
}
$user = $this->userRepo->getById($userId);
$user->email_confirmed = true;
$user->save();
$this->emailConfirmationService->deleteByUser($user);
$this->showSuccessNotification(trans('auth.email_confirm_success'));
return redirect('/login');
}
/**
* Resend the confirmation email.
*/
public function resend()
{
$user = $this->loginService->getLastLoginAttemptUser();
if ($user === null) {
$this->showErrorNotification(trans('errors.login_user_not_found'));
return redirect('/login');
}
try {
$this->emailConfirmationService->sendConfirmation($user);
} catch (ConfirmationEmailException $e) {
$this->showErrorNotification($e->getMessage());
return redirect('/login');
} catch (Exception $e) {
$this->showErrorNotification(trans('auth.email_confirm_send_error'));
return redirect('/register/awaiting');
}
$this->showSuccessNotification(trans('auth.email_confirm_resent'));
return redirect('/register/confirm');
}
}

View File

@@ -0,0 +1,65 @@
<?php
namespace BookStack\Access\Controllers;
use BookStack\Activity\ActivityType;
use BookStack\Http\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Password;
use Illuminate\Support\Sleep;
class ForgotPasswordController extends Controller
{
public function __construct()
{
$this->middleware('guest');
$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.
*/
public function sendResetLinkEmail(Request $request)
{
$this->validate($request, [
'email' => ['required', 'email'],
]);
// Add random pause to the response to help avoid time-base sniffing
// of valid resets via slower email send handling.
Sleep::for(random_int(1000, 3000))->milliseconds();
// 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 = Password::broker()->sendResetLink(
$request->only('email')
);
if ($response === Password::RESET_LINK_SENT) {
$this->logActivity(ActivityType::AUTH_PASSWORD_RESET, $request->get('email'));
}
if (in_array($response, [Password::RESET_LINK_SENT, Password::INVALID_USER, Password::RESET_THROTTLED])) {
$message = trans('auth.reset_password_sent', ['email' => $request->get('email')]);
$this->showSuccessNotification($message);
return redirect('/password/email')->with('status', trans($response));
}
// If an error was returned by the password broker, we will get this message
// translated so we can notify a user of the problem. We'll redirect back
// to where the users came from so they can attempt this process again.
return redirect('/password/email')->withErrors(
['email' => trans($response)]
);
}
}

View File

@@ -0,0 +1,25 @@
<?php
namespace BookStack\Access\Controllers;
use BookStack\Access\LoginService;
use BookStack\Exceptions\NotFoundException;
use BookStack\Users\Models\User;
trait HandlesPartialLogins
{
/**
* @throws NotFoundException
*/
protected function currentOrLastAttemptedUser(): User
{
$loginService = app()->make(LoginService::class);
$user = auth()->user() ?? $loginService->getLastLoginAttemptUser();
if (!$user) {
throw new NotFoundException(trans('errors.login_user_not_found'));
}
return $user;
}
}

View File

@@ -0,0 +1,207 @@
<?php
namespace BookStack\Access\Controllers;
use BookStack\Access\LoginService;
use BookStack\Access\SocialDriverManager;
use BookStack\Exceptions\LoginAttemptEmailNeededException;
use BookStack\Exceptions\LoginAttemptException;
use BookStack\Facades\Activity;
use BookStack\Http\Controller;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Validation\ValidationException;
class LoginController extends Controller
{
use ThrottlesLogins;
public function __construct(
protected SocialDriverManager $socialDriverManager,
protected LoginService $loginService,
) {
$this->middleware('guest', ['only' => ['getLogin', 'login']]);
$this->middleware('guard:standard,ldap', ['only' => ['login']]);
$this->middleware('guard:standard,ldap,oidc', ['only' => ['logout']]);
}
/**
* Show the application login form.
*/
public function getLogin(Request $request)
{
$socialDrivers = $this->socialDriverManager->getActive();
$authMethod = config('auth.method');
$preventInitiation = $request->get('prevent_auto_init') === 'true';
if ($request->has('email')) {
session()->flashInput([
'email' => $request->get('email'),
'password' => (config('app.env') === 'demo') ? $request->get('password', '') : '',
]);
}
// Store the previous location for redirect after login
$this->updateIntendedFromPrevious();
if (!$preventInitiation && $this->loginService->shouldAutoInitiate()) {
return view('auth.login-initiate', [
'authMethod' => $authMethod,
]);
}
return view('auth.login', [
'socialDrivers' => $socialDrivers,
'authMethod' => $authMethod,
]);
}
/**
* Handle a login request to the application.
*/
public function login(Request $request)
{
$this->validateLogin($request);
$username = $request->get($this->username());
// Check login throttling attempts to see if they've gone over the limit
if ($this->hasTooManyLoginAttempts($request)) {
Activity::logFailedLogin($username);
return $this->sendLockoutResponse($request);
}
try {
if ($this->attemptLogin($request)) {
return $this->sendLoginResponse($request);
}
} catch (LoginAttemptException $exception) {
Activity::logFailedLogin($username);
return $this->sendLoginAttemptExceptionResponse($exception, $request);
}
// On unsuccessful login attempt, Increment login attempts for throttling and log failed login.
$this->incrementLoginAttempts($request);
Activity::logFailedLogin($username);
// 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()
{
return redirect($this->loginService->logout());
}
/**
* 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.
*/
protected function attemptLogin(Request $request): bool
{
return $this->loginService->attempt(
$this->credentials($request),
auth()->getDefaultDriver(),
$request->filled('remember')
);
}
/**
* Validate the user login request.
* @throws ValidationException
*/
protected function validateLogin(Request $request): void
{
$rules = ['password' => ['required', 'string']];
$authMethod = config('auth.method');
if ($authMethod === 'standard') {
$rules['email'] = ['required', 'email'];
}
if ($authMethod === 'ldap') {
$rules['username'] = ['required', 'string'];
$rules['email'] = ['email'];
}
$request->validate($rules);
}
/**
* Send a response when a login attempt exception occurs.
*/
protected function sendLoginAttemptExceptionResponse(LoginAttemptException $exception, Request $request)
{
if ($exception instanceof LoginAttemptEmailNeededException) {
$request->flash();
session()->flash('request-email', true);
}
if ($message = $exception->getMessage()) {
$this->showWarningNotification($message);
}
return redirect('/login');
}
/**
* Update the intended URL location from their previous URL.
* Ignores if not from the current app instance or if from certain
* login or authentication routes.
*/
protected function updateIntendedFromPrevious(): void
{
// Store the previous location for redirect after login
$previous = url()->previous('');
$isPreviousFromInstance = str_starts_with($previous, url('/'));
if (!$previous || !setting('app-public') || !$isPreviousFromInstance) {
return;
}
$ignorePrefixList = [
'/login',
'/mfa',
];
foreach ($ignorePrefixList as $ignorePrefix) {
if (str_starts_with($previous, url($ignorePrefix))) {
return;
}
}
redirect()->setIntendedUrl($previous);
}
}

View File

@@ -0,0 +1,99 @@
<?php
namespace BookStack\Access\Controllers;
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\Controller;
use Exception;
use Illuminate\Http\Request;
use Illuminate\Validation\ValidationException;
class MfaBackupCodesController extends Controller
{
use HandlesPartialLogins;
protected const SETUP_SECRET_SESSION_KEY = 'mfa-setup-backup-codes';
/**
* Show a view that generates and displays backup codes.
*/
public function generate(BackupCodeService $codeService)
{
$codes = $codeService->generateNewSet();
session()->put(self::SETUP_SECRET_SESSION_KEY, encrypt($codes));
$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,
]);
}
/**
* Confirm the setup of backup codes, storing them against the user.
*
* @throws Exception
*/
public function confirm()
{
if (!session()->has(self::SETUP_SECRET_SESSION_KEY)) {
return response('No generated codes found in the session', 500);
}
$codes = decrypt(session()->pull(self::SETUP_SECRET_SESSION_KEY));
MfaValue::upsertWithValue($this->currentOrLastAttemptedUser(), MfaValue::METHOD_BACKUP_CODES, json_encode($codes));
$this->logActivity(ActivityType::MFA_SETUP_METHOD, 'backup-codes');
if (!auth()->check()) {
$this->showSuccessNotification(trans('auth.mfa_setup_login_notification'));
return redirect('/login');
}
return redirect('/mfa/setup');
}
/**
* Verify the MFA method submission on check.
*
* @throws NotFoundException
* @throws ValidationException
*/
public function verify(Request $request, BackupCodeService $codeService, MfaSession $mfaSession, LoginService $loginService)
{
$user = $this->currentOrLastAttemptedUser();
$codes = MfaValue::getValueForUser($user, MfaValue::METHOD_BACKUP_CODES) ?? '[]';
$this->validate($request, [
'code' => [
'required', 'max:12', 'min:8',
function ($attribute, $value, $fail) use ($codeService, $codes) {
if (!$codeService->inputCodeExistsInSet($value, $codes)) {
$fail(trans('validation.backup_codes'));
}
},
],
]);
$updatedCodes = $codeService->removeInputCodeFromSet($request->get('code'), $codes);
MfaValue::upsertWithValue($user, MfaValue::METHOD_BACKUP_CODES, $updatedCodes);
$mfaSession->markVerifiedForUser($user);
$loginService->reattemptLoginFor($user);
if ($codeService->countCodesInSet($updatedCodes) < 5) {
$this->showWarningNotification(trans('auth.mfa_backup_codes_usage_limit_warning'));
}
return redirect()->intended();
}
}

View File

@@ -0,0 +1,73 @@
<?php
namespace BookStack\Access\Controllers;
use BookStack\Access\Mfa\MfaValue;
use BookStack\Activity\ActivityType;
use BookStack\Http\Controller;
use Illuminate\Http\Request;
class MfaController extends Controller
{
use HandlesPartialLogins;
/**
* Show the view to setup MFA for the current user.
*/
public function setup()
{
$userMethods = $this->currentOrLastAttemptedUser()
->mfaValues()
->get(['id', 'method'])
->groupBy('method');
$this->setPageTitle(trans('auth.mfa_setup'));
return view('mfa.setup', [
'userMethods' => $userMethods,
]);
}
/**
* Remove an MFA method for the current user.
*
* @throws \Exception
*/
public function remove(string $method)
{
if (in_array($method, MfaValue::allMethods())) {
$value = user()->mfaValues()->where('method', '=', $method)->first();
if ($value) {
$value->delete();
$this->logActivity(ActivityType::MFA_REMOVE_METHOD, $method);
}
}
return redirect('/mfa/setup');
}
/**
* Show the page to start an MFA verification.
*/
public function verify(Request $request)
{
$desiredMethod = $request->get('method');
$userMethods = $this->currentOrLastAttemptedUser()
->mfaValues()
->get(['id', 'method'])
->groupBy('method');
// Basic search for the default option for a user.
// (Prioritises totp over backup codes)
$method = $userMethods->has($desiredMethod) ? $desiredMethod : $userMethods->keys()->sort()->reverse()->first();
$otherMethods = $userMethods->keys()->filter(function ($userMethod) use ($method) {
return $method !== $userMethod;
})->all();
return view('mfa.verify', [
'userMethods' => $userMethods,
'method' => $method,
'otherMethods' => $otherMethods,
]);
}
}

View File

@@ -0,0 +1,104 @@
<?php
namespace BookStack\Access\Controllers;
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\Controller;
use Illuminate\Http\Request;
use Illuminate\Validation\ValidationException;
class MfaTotpController extends Controller
{
use HandlesPartialLogins;
protected const SETUP_SECRET_SESSION_KEY = 'mfa-setup-totp-secret';
public function __construct(
protected TotpService $totp
) {
}
/**
* Show a view that generates and displays a TOTP QR code.
*/
public function generate()
{
if (session()->has(static::SETUP_SECRET_SESSION_KEY)) {
$totpSecret = decrypt(session()->get(static::SETUP_SECRET_SESSION_KEY));
} else {
$totpSecret = $this->totp->generateSecret();
session()->put(static::SETUP_SECRET_SESSION_KEY, encrypt($totpSecret));
}
$qrCodeUrl = $this->totp->generateUrl($totpSecret, $this->currentOrLastAttemptedUser());
$svg = $this->totp->generateQrCodeSvg($qrCodeUrl);
$this->setPageTitle(trans('auth.mfa_gen_totp_title'));
return view('mfa.totp-generate', [
'url' => $qrCodeUrl,
'svg' => $svg,
]);
}
/**
* Confirm the setup of TOTP and save the auth method secret
* against the current user.
*
* @throws ValidationException
* @throws NotFoundException
*/
public function confirm(Request $request)
{
$totpSecret = decrypt(session()->get(static::SETUP_SECRET_SESSION_KEY));
$this->validate($request, [
'code' => [
'required',
'max:12', 'min:4',
new TotpValidationRule($totpSecret, $this->totp),
],
]);
MfaValue::upsertWithValue($this->currentOrLastAttemptedUser(), MfaValue::METHOD_TOTP, $totpSecret);
session()->remove(static::SETUP_SECRET_SESSION_KEY);
$this->logActivity(ActivityType::MFA_SETUP_METHOD, 'totp');
if (!auth()->check()) {
$this->showSuccessNotification(trans('auth.mfa_setup_login_notification'));
return redirect('/login');
}
return redirect('/mfa/setup');
}
/**
* Verify the MFA method submission on check.
*
* @throws NotFoundException
*/
public function verify(Request $request, LoginService $loginService, MfaSession $mfaSession)
{
$user = $this->currentOrLastAttemptedUser();
$totpSecret = MfaValue::getValueForUser($user, MfaValue::METHOD_TOTP);
$this->validate($request, [
'code' => [
'required',
'max:12', 'min:4',
new TotpValidationRule($totpSecret, $this->totp),
],
]);
$mfaSession->markVerifiedForUser($user);
$loginService->reattemptLoginFor($user);
return redirect()->intended();
}
}

View File

@@ -0,0 +1,71 @@
<?php
namespace BookStack\Access\Controllers;
use BookStack\Access\Oidc\OidcException;
use BookStack\Access\Oidc\OidcService;
use BookStack\Http\Controller;
use Illuminate\Http\Request;
class OidcController extends Controller
{
protected OidcService $oidcService;
public function __construct(OidcService $oidcService)
{
$this->oidcService = $oidcService;
$this->middleware('guard:oidc');
}
/**
* Start the authorization login flow via OIDC.
*/
public function 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']);
}
/**
* Authorization flow redirect callback.
* Processes authorization response from the OIDC Authorization Server.
*/
public function callback(Request $request)
{
$storedState = session()->pull('oidc_state');
$responseState = $request->query('state');
if ($storedState !== $responseState) {
$this->showErrorNotification(trans('errors.oidc_fail_authed', ['system' => config('oidc.name')]));
return redirect('/login');
}
try {
$this->oidcService->processAuthorizeResponse($request->query('code'));
} catch (OidcException $oidcException) {
$this->showErrorNotification($oidcException->getMessage());
return redirect('/login');
}
return redirect()->intended();
}
/**
* Log the user out then start the OIDC RP-initiated logout process.
*/
public function logout()
{
return redirect($this->oidcService->logout());
}
}

View File

@@ -0,0 +1,83 @@
<?php
namespace BookStack\Access\Controllers;
use BookStack\Access\LoginService;
use BookStack\Access\RegistrationService;
use BookStack\Access\SocialDriverManager;
use BookStack\Exceptions\StoppedAuthenticationException;
use BookStack\Exceptions\UserRegistrationException;
use BookStack\Http\Controller;
use Illuminate\Contracts\Validation\Validator as ValidatorContract;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rules\Password;
class RegisterController extends Controller
{
public function __construct(
protected SocialDriverManager $socialDriverManager,
protected RegistrationService $registrationService,
protected LoginService $loginService
) {
$this->middleware('guest');
$this->middleware('guard:standard');
}
/**
* Show the application registration form.
*
* @throws UserRegistrationException
*/
public function getRegister()
{
$this->registrationService->ensureRegistrationAllowed();
$socialDrivers = $this->socialDriverManager->getActive();
return view('auth.register', [
'socialDrivers' => $socialDrivers,
]);
}
/**
* Handle a registration request for the application.
*
* @throws UserRegistrationException
* @throws StoppedAuthenticationException
*/
public function postRegister(Request $request)
{
$this->registrationService->ensureRegistrationAllowed();
$this->validator($request->all())->validate();
$userData = $request->all();
try {
$user = $this->registrationService->registerUser($userData);
$this->loginService->login($user, auth()->getDefaultDriver());
} catch (UserRegistrationException $exception) {
if ($exception->getMessage()) {
$this->showErrorNotification($exception->getMessage());
}
return redirect($exception->redirectLocation);
}
$this->showSuccessNotification(trans('auth.register_success'));
return redirect('/');
}
/**
* Get a validator for an incoming registration request.
*/
protected function validator(array $data): ValidatorContract
{
return Validator::make($data, [
'name' => ['required', 'min:2', 'max:100'],
'email' => ['required', 'email', 'max:255', 'unique:users'],
'password' => ['required', Password::default()],
// Basic honey for bots that must not be filled in
'username' => ['prohibited'],
]);
}
}

View File

@@ -0,0 +1,95 @@
<?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
{
public function __construct(
protected LoginService $loginService
) {
$this->middleware('guest');
$this->middleware('guard:standard');
}
/**
* 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, $request->get('token'));
}
/**
* 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, string $token): 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("/password/reset/{$token}")
->withInput($request->only('email'))
->withErrors(['email' => trans($response)]);
}
}

View File

@@ -0,0 +1,128 @@
<?php
namespace BookStack\Access\Controllers;
use BookStack\Access\Saml2Service;
use BookStack\Http\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Str;
class Saml2Controller extends Controller
{
public function __construct(
protected Saml2Service $samlService
) {
$this->middleware('guard:saml2');
}
/**
* Start the login flow via SAML2.
*/
public function login()
{
$loginDetails = $this->samlService->login();
session()->flash('saml2_request_id', $loginDetails['id']);
return redirect($loginDetails['url']);
}
/**
* Start the logout flow via SAML2.
*/
public function logout()
{
$user = user();
if ($user->isGuest()) {
return redirect('/login');
}
$logoutDetails = $this->samlService->logout($user);
if ($logoutDetails['id']) {
session()->flash('saml2_logout_request_id', $logoutDetails['id']);
}
return redirect($logoutDetails['url']);
}
/*
* Get the metadata for this SAML2 service provider.
*/
public function metadata()
{
$metaData = $this->samlService->metadata();
return response()->make($metaData, 200, [
'Content-Type' => 'text/xml',
]);
}
/**
* Single logout service.
* Handle logout requests and responses.
*/
public function sls()
{
$requestId = session()->pull('saml2_logout_request_id', null);
$redirect = $this->samlService->processSlsResponse($requestId);
return redirect($redirect);
}
/**
* Assertion Consumer Service start URL. Takes the SAMLResponse from the IDP.
* Due to being an external POST request, we likely won't have context of the
* current user session due to lax cookies. To work around this we store the
* SAMLResponse data and redirect to the processAcs endpoint for the actual
* processing of the request with proper context of the user session.
*/
public function startAcs(Request $request)
{
$samlResponse = $request->get('SAMLResponse', null);
if (empty($samlResponse)) {
$this->showErrorNotification(trans('errors.saml_fail_authed', ['system' => config('saml2.name')]));
return redirect('/login');
}
$acsId = Str::random(16);
$cacheKey = 'saml2_acs:' . $acsId;
cache()->set($cacheKey, encrypt($samlResponse), 10);
return redirect()->guest('/saml2/acs?id=' . $acsId);
}
/**
* Assertion Consumer Service process endpoint.
* Processes the SAML response from the IDP with context of the current session.
* Takes the SAML request from the cache, added by the startAcs method above.
*/
public function processAcs(Request $request)
{
$acsId = $request->get('id', null);
$cacheKey = 'saml2_acs:' . $acsId;
$samlResponse = null;
try {
$samlResponse = decrypt(cache()->pull($cacheKey));
} catch (\Exception $exception) {
}
$requestId = session()->pull('saml2_request_id', null);
if (empty($acsId) || empty($samlResponse)) {
$this->showErrorNotification(trans('errors.saml_fail_authed', ['system' => config('saml2.name')]));
return redirect('/login');
}
$user = $this->samlService->processAcsResponse($requestId, $samlResponse);
if (is_null($user)) {
$this->showErrorNotification(trans('errors.saml_fail_authed', ['system' => config('saml2.name')]));
return redirect('/login');
}
return redirect()->intended();
}
}

View File

@@ -0,0 +1,137 @@
<?php
namespace BookStack\Access\Controllers;
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\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Str;
use Laravel\Socialite\Contracts\User as SocialUser;
class SocialController extends Controller
{
public function __construct(
protected SocialAuthService $socialAuthService,
protected RegistrationService $registrationService,
protected LoginService $loginService,
) {
$this->middleware('guest')->only(['register']);
}
/**
* Redirect to the relevant social site.
*
* @throws SocialDriverNotConfigured
*/
public function login(string $socialDriver)
{
session()->put('social-callback', 'login');
return $this->socialAuthService->startLogIn($socialDriver);
}
/**
* Redirect to the social site for authentication intended to register.
*
* @throws SocialDriverNotConfigured
* @throws UserRegistrationException
*/
public function register(string $socialDriver)
{
$this->registrationService->ensureRegistrationAllowed();
session()->put('social-callback', 'register');
return $this->socialAuthService->startRegister($socialDriver);
}
/**
* The callback for social login services.
*
* @throws SocialSignInException
* @throws SocialDriverNotConfigured
* @throws UserRegistrationException
*/
public function callback(Request $request, string $socialDriver)
{
if (!session()->has('social-callback')) {
throw new SocialSignInException(trans('errors.social_no_action_defined'), '/login');
}
// Check request for error information
if ($request->has('error') && $request->has('error_description')) {
throw new SocialSignInException(trans('errors.social_login_bad_response', [
'socialAccount' => $socialDriver,
'error' => $request->get('error_description'),
]), '/login');
}
$action = session()->pull('social-callback');
// Attempt login or fall-back to register if allowed.
$socialUser = $this->socialAuthService->getSocialUser($socialDriver);
if ($action === 'login') {
try {
return $this->socialAuthService->handleLoginCallback($socialDriver, $socialUser);
} catch (SocialSignInAccountNotUsed $exception) {
if ($this->socialAuthService->drivers()->isAutoRegisterEnabled($socialDriver)) {
return $this->socialRegisterCallback($socialDriver, $socialUser);
}
throw $exception;
}
}
if ($action === 'register') {
return $this->socialRegisterCallback($socialDriver, $socialUser);
}
return redirect('/');
}
/**
* Detach a social account from a user.
*/
public function detach(string $socialDriver)
{
$this->socialAuthService->detachSocialAccount($socialDriver);
session()->flash('success', trans('settings.users_social_disconnected', ['socialAccount' => Str::title($socialDriver)]));
return redirect('/my-account/auth#social-accounts');
}
/**
* Register a new user after a registration callback.
*
* @throws UserRegistrationException
*/
protected function socialRegisterCallback(string $socialDriver, SocialUser $socialUser)
{
$socialUser = $this->socialAuthService->handleRegistrationCallback($socialDriver, $socialUser);
$socialAccount = $this->socialAuthService->newSocialAccount($socialDriver, $socialUser);
$emailVerified = $this->socialAuthService->drivers()->isAutoConfirmEmailEnabled($socialDriver);
// Create an array of the user data to create a new user instance
$userData = [
'name' => $socialUser->getName(),
'email' => $socialUser->getEmail(),
'password' => Str::random(32),
];
// Take name from email address if empty
if (!$userData['name']) {
$userData['name'] = explode('@', $userData['email'])[0];
}
$user = $this->registrationService->registerUser($userData, $socialAccount, $emailVerified);
$this->showSuccessNotification(trans('auth.register_success'));
$this->loginService->login($user, $socialDriver);
return redirect('/');
}
}

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()->make(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,24 +1,23 @@
<?php
namespace BookStack\Http\Controllers\Auth;
namespace BookStack\Access\Controllers;
use BookStack\Actions\ActivityType;
use BookStack\Auth\Access\UserInviteService;
use BookStack\Auth\UserRepo;
use BookStack\Access\UserInviteService;
use BookStack\Exceptions\UserTokenExpiredException;
use BookStack\Exceptions\UserTokenNotFoundException;
use BookStack\Facades\Theme;
use BookStack\Http\Controllers\Controller;
use BookStack\Theming\ThemeEvents;
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.
@@ -34,6 +33,7 @@ class UserInviteController extends Controller
/**
* Show the page for the user to set the password for their account.
*
* @throws Exception
*/
public function showSetPassword(string $token)
@@ -51,12 +51,13 @@ class UserInviteController extends Controller
/**
* Sets the password for an invited user and then grants them access.
*
* @throws Exception
*/
public function setPassword(Request $request, string $token)
{
$this->validate($request, [
'password' => 'required|min:8'
'password' => ['required', Password::default()],
]);
try {
@@ -66,23 +67,22 @@ 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();
auth()->login($user);
Theme::dispatch(ThemeEvents::AUTH_LOGIN, auth()->getDefaultDriver(), $user);
$this->logActivity(ActivityType::AUTH_LOGIN, $user);
$this->showSuccessNotification(trans('auth.user_invite_success', ['appName' => setting('app-name')]));
$this->inviteService->deleteByUser($user);
$this->showSuccessNotification(trans('auth.user_invite_success_login', ['appName' => setting('app-name')]));
return redirect('/');
return redirect('/login');
}
/**
* Check and validate the exception thrown when checking an invite token.
* @return RedirectResponse|Redirector
*
* @throws Exception
*
* @return RedirectResponse|Redirector
*/
protected function handleTokenException(Exception $exception)
{
@@ -92,6 +92,7 @@ class UserInviteController extends Controller
if ($exception instanceof UserTokenExpiredException) {
$this->showErrorNotification(trans('errors.invite_token_expired'));
return redirect('/password/email');
}

View File

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

View File

@@ -0,0 +1,65 @@
<?php
namespace BookStack\Access;
use BookStack\Users\Models\User;
use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Contracts\Auth\UserProvider;
class ExternalBaseUserProvider implements UserProvider
{
/**
* Retrieve a user by their unique identifier.
*/
public function retrieveById(mixed $identifier): ?Authenticatable
{
return User::query()->find($identifier);
}
/**
* Retrieve a user by their unique identifier and "remember me" token.
*
* @param string $token
*/
public function retrieveByToken(mixed $identifier, $token): null
{
return null;
}
/**
* Update the "remember me" token for the given user in storage.
*
* @param Authenticatable $user
* @param string $token
*
* @return void
*/
public function updateRememberToken(Authenticatable $user, $token)
{
//
}
/**
* Retrieve a user by the given credentials.
*/
public function retrieveByCredentials(array $credentials): ?Authenticatable
{
return User::query()
->where('external_auth_id', $credentials['external_auth_id'])
->first();
}
/**
* Validate a user against the given credentials.
*/
public function validateCredentials(Authenticatable $user, array $credentials): bool
{
// Should be done in the guard.
return false;
}
public function rehashPasswordIfRequired(Authenticatable $user, #[\SensitiveParameter] array $credentials, bool $force = false)
{
// No action to perform, any passwords are external in the auth system
}
}

View File

@@ -0,0 +1,86 @@
<?php
namespace BookStack\Access;
use BookStack\Users\Models\Role;
use BookStack\Users\Models\User;
use Illuminate\Support\Collection;
class GroupSyncService
{
/**
* Check a role against an array of group names to see if it matches.
* Checked against role 'external_auth_id' if set otherwise the name of the role.
*/
protected function roleMatchesGroupNames(Role $role, array $groupNames): bool
{
if ($role->external_auth_id) {
return $this->externalIdMatchesGroupNames($role->external_auth_id, $groupNames);
}
$roleName = str_replace(' ', '-', trim(strtolower($role->display_name)));
return in_array($roleName, $groupNames);
}
/**
* Check if the given external auth ID string matches one of the given group names.
*/
protected function externalIdMatchesGroupNames(string $externalId, array $groupNames): bool
{
foreach ($this->parseRoleExternalAuthId($externalId) as $externalAuthId) {
if (in_array($externalAuthId, $groupNames)) {
return true;
}
}
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.
*/
protected function matchGroupsToSystemsRoles(array $groupNames): Collection
{
foreach ($groupNames as $i => $groupName) {
$groupNames[$i] = str_replace(' ', '-', trim(strtolower($groupName)));
}
$roles = Role::query()->get(['id', 'external_auth_id', 'display_name']);
$matchedRoles = $roles->filter(function (Role $role) use ($groupNames) {
return $this->roleMatchesGroupNames($role, $groupNames);
});
return $matchedRoles->pluck('id');
}
/**
* Sync the groups to the user roles for the current user.
*/
public function syncUserWithFoundGroups(User $user, array $userGroups, bool $detachExisting): void
{
// Get the ids for the roles from the names
$groupsAsRoles = $this->matchGroupsToSystemsRoles($userGroups);
// Sync groups
if ($detachExisting) {
$user->roles()->sync($groupsAsRoles);
$user->attachDefaultRole();
} else {
$user->roles()->syncWithoutDetaching($groupsAsRoles);
}
}
}

View File

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

View File

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

View File

@@ -1,22 +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\LoginAttemptException;
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.
@@ -35,17 +35,15 @@ class LdapSessionGuard extends ExternalBaseSessionGuard
/**
* Validate a user's credentials.
*
* @param array $credentials
* @return bool
* @throws LdapException
*/
public function validate(array $credentials = [])
public function validate(array $credentials = []): bool
{
$userDetails = $this->ldapService->getUserDetails($credentials['username']);
if (isset($userDetails['uid'])) {
$this->lastAttempted = $this->provider->retrieveByCredentials([
'external_auth_id' => $userDetails['uid']
'external_auth_id' => $userDetails['uid'],
]);
}
@@ -55,13 +53,13 @@ class LdapSessionGuard extends ExternalBaseSessionGuard
/**
* Attempt to authenticate a user using the given credentials.
*
* @param array $credentials
* @param bool $remember
* @return bool
* @throws LoginAttemptException
* @param bool $remember
*
* @throws LdapException
* @throws LoginAttemptException
* @throws JsonDebugException
*/
public function attempt(array $credentials = [], $remember = false)
public function attempt(array $credentials = [], $remember = false): bool
{
$username = $credentials['username'];
$userDetails = $this->ldapService->getUserDetails($username);
@@ -69,7 +67,7 @@ class LdapSessionGuard extends ExternalBaseSessionGuard
$user = null;
if (isset($userDetails['uid'])) {
$this->lastAttempted = $user = $this->provider->retrieveByCredentials([
'external_auth_id' => $userDetails['uid']
'external_auth_id' => $userDetails['uid'],
]);
}
@@ -81,7 +79,7 @@ class LdapSessionGuard extends ExternalBaseSessionGuard
try {
$user = $this->createNewFromLdapAndCreds($userDetails, $credentials);
} catch (UserRegistrationException $exception) {
throw new LoginAttemptException($exception->message);
throw new LoginAttemptException($exception->getMessage());
}
}
@@ -91,16 +89,18 @@ class LdapSessionGuard extends ExternalBaseSessionGuard
}
// Attach avatar if non-existent
if (is_null($user->avatar)) {
if (!$user->avatar()->exists()) {
$this->ldapService->saveAndAttachAvatar($user, $userDetails);
}
$this->login($user, $remember);
return true;
}
/**
* Create a new user from the given ldap credentials and login credentials
* Create a new user from the given ldap credentials and login credentials.
*
* @throws LoginAttemptEmailNeededException
* @throws LoginAttemptException
* @throws UserRegistrationException
@@ -114,14 +114,15 @@ class LdapSessionGuard extends ExternalBaseSessionGuard
}
$details = [
'name' => $ldapUserDetails['name'],
'email' => $ldapUserDetails['email'] ?: $credentials['email'],
'name' => $ldapUserDetails['name'],
'email' => $ldapUserDetails['email'] ?: $credentials['email'],
'external_auth_id' => $ldapUserDetails['uid'],
'password' => Str::random(32),
'password' => Str::random(32),
];
$user = $this->registrationService->registerUser($details, null, false);
$this->ldapService->saveAndAttachAvatar($user, $ldapUserDetails);
return $user;
}
}

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

@@ -0,0 +1,122 @@
<?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 \LDAP\Result|array|false
*/
public function search($ldapConnection, string $baseDn, string $filter, array $attributes = [])
{
return ldap_search($ldapConnection, $baseDn, $filter, $attributes);
}
/**
* Read an entry from the LDAP tree.
*
* @param resource|\Ldap\Connection $ldapConnection
*
* @return \LDAP\Result|array|false
*/
public function read($ldapConnection, string $baseDn, string $filter, array $attributes = [])
{
return ldap_read($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 = []): 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);
}
}

478
app/Access/LdapService.php Normal file
View File

@@ -0,0 +1,478 @@
<?php
namespace BookStack\Access;
use BookStack\Exceptions\JsonDebugException;
use BookStack\Exceptions\LdapException;
use BookStack\Uploads\UserAvatars;
use BookStack\Users\Models\User;
use ErrorException;
use Illuminate\Support\Facades\Log;
/**
* Class LdapService
* Handles any app-specific LDAP tasks.
*/
class LdapService
{
/**
* @var resource|\LDAP\Connection
*/
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';
}
/**
* Check if groups should be synced.
*/
public function shouldSyncGroups(): bool
{
return $this->enabled && $this->config['user_to_groups'] !== false;
}
/**
* Search for attributes for a specific user on the ldap.
*
* @throws LdapException
*/
private function getUserWithAttributes(string $userName, array $attributes): ?array
{
$ldapConnection = $this->getConnection();
$this->bindSystemUser($ldapConnection);
// Clean attributes
foreach ($attributes as $index => $attribute) {
if (str_starts_with($attribute, 'BIN;')) {
$attributes[$index] = substr($attribute, strlen('BIN;'));
}
}
// Find user
$userFilter = $this->buildFilter($this->config['user_filter'], ['user' => $userName]);
$baseDn = $this->config['base_dn'];
$followReferrals = $this->config['follow_referrals'] ? 1 : 0;
$this->ldap->setOption($ldapConnection, LDAP_OPT_REFERRALS, $followReferrals);
$users = $this->ldap->searchAndGetEntries($ldapConnection, $baseDn, $userFilter, $attributes);
if ($users['count'] === 0) {
return null;
}
return $users[0];
}
/**
* Build the user display name from the (potentially multiple) attributes defined by the configuration.
*/
protected function getUserDisplayName(array $userDetails, array $displayNameAttrs, string $defaultValue): string
{
$displayNameParts = [];
foreach ($displayNameAttrs as $dnAttr) {
$dnComponent = $this->getUserResponseProperty($userDetails, $dnAttr, null);
if ($dnComponent) {
$displayNameParts[] = $dnComponent;
}
}
if (empty($displayNameParts)) {
return $defaultValue;
}
return implode(' ', $displayNameParts);
}
/**
* Get the details of a user from LDAP using the given username.
* User found via configurable user filter.
*
* @throws LdapException|JsonDebugException
*/
public function getUserDetails(string $userName): ?array
{
$idAttr = $this->config['id_attribute'];
$emailAttr = $this->config['email_attribute'];
$displayNameAttrs = explode('|', $this->config['display_name_attribute']);
$thumbnailAttr = $this->config['thumbnail_attribute'];
$user = $this->getUserWithAttributes($userName, array_filter([
'cn', 'dn', $idAttr, $emailAttr, ...$displayNameAttrs, $thumbnailAttr,
]));
if (is_null($user)) {
return null;
}
$nameDefault = $this->getUserResponseProperty($user, 'cn', null);
if (is_null($nameDefault)) {
$nameDefault = ldap_explode_dn($user['dn'], 1)[0] ?? $user['dn'];
}
$formatted = [
'uid' => $this->getUserResponseProperty($user, $idAttr, $user['dn']),
'name' => $this->getUserDisplayName($user, $displayNameAttrs, $nameDefault),
'dn' => $user['dn'],
'email' => $this->getUserResponseProperty($user, $emailAttr, null),
'avatar' => $thumbnailAttr ? $this->getUserResponseProperty($user, $thumbnailAttr, null) : null,
];
if ($this->config['dump_user_details']) {
throw new JsonDebugException([
'details_from_ldap' => $user,
'details_bookstack_parsed' => $formatted,
]);
}
return $formatted;
}
/**
* Get a property from an LDAP user response fetch.
* Handles properties potentially being part of an array.
* If the given key is prefixed with 'BIN;', that indicator will be stripped
* from the key and any fetched values will be converted from binary to hex.
*/
protected function getUserResponseProperty(array $userDetails, string $propertyKey, $defaultValue)
{
$isBinary = str_starts_with($propertyKey, 'BIN;');
$propertyKey = strtolower($propertyKey);
$value = $defaultValue;
if ($isBinary) {
$propertyKey = substr($propertyKey, strlen('BIN;'));
}
if (isset($userDetails[$propertyKey])) {
$value = (is_array($userDetails[$propertyKey]) ? $userDetails[$propertyKey][0] : $userDetails[$propertyKey]);
if ($isBinary) {
$value = bin2hex($value);
}
}
return $value;
}
/**
* Check if the given credentials are valid for the given user.
*
* @throws LdapException
*/
public function validateUserCredentials(?array $ldapUserDetails, string $password): bool
{
if (is_null($ldapUserDetails)) {
return false;
}
$ldapConnection = $this->getConnection();
try {
$ldapBind = $this->ldap->bind($ldapConnection, $ldapUserDetails['dn'], $password);
} catch (ErrorException $e) {
$ldapBind = false;
}
return $ldapBind;
}
/**
* Bind the system user to the LDAP connection using the given credentials
* otherwise anonymous access is attempted.
*
* @param resource|\LDAP\Connection $connection
*
* @throws LdapException
*/
protected function bindSystemUser($connection): void
{
$ldapDn = $this->config['dn'];
$ldapPass = $this->config['pass'];
$isAnonymous = ($ldapDn === false || $ldapPass === false);
if ($isAnonymous) {
$ldapBind = $this->ldap->bind($connection);
} else {
$ldapBind = $this->ldap->bind($connection, $ldapDn, $ldapPass);
}
if (!$ldapBind) {
throw new LdapException(($isAnonymous ? trans('errors.ldap_fail_anonymous') : trans('errors.ldap_fail_authed')));
}
}
/**
* Get the connection to the LDAP server.
* Creates a new connection if one does not exist.
*
* @throws LdapException
*
* @return resource|\LDAP\Connection
*/
protected function getConnection()
{
if ($this->ldapConnection !== null) {
return $this->ldapConnection;
}
// Check LDAP extension in installed
if (!function_exists('ldap_connect') && config('app.env') !== 'testing') {
throw new LdapException(trans('errors.ldap_extension_not_installed'));
}
// Disable certificate verification.
// This option works globally and must be set before a connection is created.
if ($this->config['tls_insecure']) {
$this->ldap->setOption(null, LDAP_OPT_X_TLS_REQUIRE_CERT, LDAP_OPT_X_TLS_NEVER);
}
// Configure any user-provided CA cert files for LDAP.
// This option works globally and must be set before a connection is created.
if ($this->config['tls_ca_cert']) {
$this->configureTlsCaCerts($this->config['tls_ca_cert']);
}
$ldapHost = $this->parseServerString($this->config['server']);
$ldapConnection = $this->ldap->connect($ldapHost);
if ($ldapConnection === false) {
throw new LdapException(trans('errors.ldap_cannot_connect'));
}
// Set any required options
if ($this->config['version']) {
$this->ldap->setVersion($ldapConnection, $this->config['version']);
}
// Start and verify TLS if it's enabled
if ($this->config['start_tls']) {
try {
$started = $this->ldap->startTls($ldapConnection);
} catch (\Exception $exception) {
$error = $exception->getMessage() . ' :: ' . ldap_error($ldapConnection);
ldap_get_option($ldapConnection, LDAP_OPT_DIAGNOSTIC_MESSAGE, $detail);
Log::info("LDAP STARTTLS failure: {$error} {$detail}");
throw new LdapException('Could not start TLS connection. Further details in the application log.');
}
if (!$started) {
throw new LdapException('Could not start TLS connection');
}
}
$this->ldapConnection = $ldapConnection;
return $this->ldapConnection;
}
/**
* Configure TLS CA certs globally for ldap use.
* This will detect if the given path is a directory or file, and set the relevant
* LDAP TLS options appropriately otherwise throw an exception if no file/folder found.
*
* Note: When using a folder, certificates are expected to be correctly named by hash
* which can be done via the c_rehash utility.
*
* @throws LdapException
*/
protected function configureTlsCaCerts(string $caCertPath): void
{
$errMessage = "Provided path [{$caCertPath}] for LDAP TLS CA certs could not be resolved to an existing location";
$path = realpath($caCertPath);
if ($path === false) {
throw new LdapException($errMessage);
}
if (is_dir($path)) {
$this->ldap->setOption(null, LDAP_OPT_X_TLS_CACERTDIR, $path);
} else if (is_file($path)) {
$this->ldap->setOption(null, LDAP_OPT_X_TLS_CACERTFILE, $path);
} else {
throw new LdapException($errMessage);
}
}
/**
* 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): string
{
if (str_starts_with($serverString, 'ldaps://') || str_starts_with($serverString, 'ldap://')) {
return $serverString;
}
return "ldap://{$serverString}";
}
/**
* Build a filter string by injecting common variables.
* Both "${var}" and "{var}" style placeholders are supported.
* Dollar based are old format but supported for compatibility.
*/
protected function buildFilter(string $filterString, array $attrs): string
{
$newAttrs = [];
foreach ($attrs as $key => $attrText) {
$escapedText = $this->ldap->escape($attrText);
$oldVarKey = '${' . $key . '}';
$newVarKey = '{' . $key . '}';
$newAttrs[$oldVarKey] = $escapedText;
$newAttrs[$newVarKey] = $escapedText;
}
return strtr($filterString, $newAttrs);
}
/**
* Get the groups a user is a part of on ldap.
*
* @throws LdapException
* @throws JsonDebugException
*/
public function getUserGroups(string $userName): array
{
$groupsAttr = $this->config['group_attribute'];
$user = $this->getUserWithAttributes($userName, [$groupsAttr]);
if ($user === null) {
return [];
}
$userGroups = $this->extractGroupsFromSearchResponseEntry($user);
$allGroups = $this->getGroupsRecursive($userGroups, []);
$formattedGroups = $this->extractGroupNamesFromLdapGroupDns($allGroups);
if ($this->config['dump_user_groups']) {
throw new JsonDebugException([
'details_from_ldap' => $user,
'parsed_direct_user_groups' => $userGroups,
'parsed_recursive_user_groups' => $allGroups,
'parsed_resulting_group_names' => $formattedGroups,
]);
}
return $formattedGroups;
}
protected function extractGroupNamesFromLdapGroupDns(array $groupDNs): array
{
$names = [];
foreach ($groupDNs as $groupDN) {
$exploded = $this->ldap->explodeDn($groupDN, 1);
if ($exploded !== false && count($exploded) > 0) {
$names[] = $exploded[0];
}
}
return array_unique($names);
}
/**
* Build an array of all relevant groups DNs after recursively scanning
* across parents of the groups given.
*
* @throws LdapException
*/
protected function getGroupsRecursive(array $groupDNs, array $checked): array
{
$groupsToAdd = [];
foreach ($groupDNs as $groupDN) {
if (in_array($groupDN, $checked)) {
continue;
}
$parentGroups = $this->getParentsOfGroup($groupDN);
$groupsToAdd = array_merge($groupsToAdd, $parentGroups);
$checked[] = $groupDN;
}
$uniqueDNs = array_unique(array_merge($groupDNs, $groupsToAdd), SORT_REGULAR);
if (empty($groupsToAdd)) {
return $uniqueDNs;
}
return $this->getGroupsRecursive($uniqueDNs, $checked);
}
/**
* @throws LdapException
*/
protected function getParentsOfGroup(string $groupDN): array
{
$groupsAttr = strtolower($this->config['group_attribute']);
$ldapConnection = $this->getConnection();
$this->bindSystemUser($ldapConnection);
$followReferrals = $this->config['follow_referrals'] ? 1 : 0;
$this->ldap->setOption($ldapConnection, LDAP_OPT_REFERRALS, $followReferrals);
$read = $this->ldap->read($ldapConnection, $groupDN, '(objectClass=*)', [$groupsAttr]);
$results = $this->ldap->getEntries($ldapConnection, $read);
if ($results['count'] === 0) {
return [];
}
return $this->extractGroupsFromSearchResponseEntry($results[0]);
}
/**
* Extract an array of group DN values from the given LDAP search response entry
*/
protected function extractGroupsFromSearchResponseEntry(array $ldapEntry): array
{
$groupsAttr = strtolower($this->config['group_attribute']);
$groupDNs = [];
$count = 0;
if (isset($ldapEntry[$groupsAttr]['count'])) {
$count = (int) $ldapEntry[$groupsAttr]['count'];
}
for ($i = 0; $i < $count; $i++) {
$dn = $ldapEntry[$groupsAttr][$i];
if (!in_array($dn, $groupDNs)) {
$groupDNs[] = $dn;
}
}
return $groupDNs;
}
/**
* Sync the LDAP groups to the user roles for the current user.
*
* @throws LdapException
* @throws JsonDebugException
*/
public function syncGroups(User $user, string $username): void
{
$userLdapGroups = $this->getUserGroups($username);
$this->groupSyncService->syncUserWithFoundGroups($user, $userLdapGroups, $this->config['remove_from_groups']);
}
/**
* Save and attach an avatar image, if found in the ldap details, and attach
* to the given user model.
*/
public function saveAndAttachAvatar(User $user, array $ldapUserDetails): void
{
if (is_null(config('services.ldap.thumbnail_attribute')) || is_null($ldapUserDetails['avatar'])) {
return;
}
try {
$imageData = $ldapUserDetails['avatar'];
$this->userAvatars->assignToUserFromExistingData($user, $imageData, 'jpg');
} catch (\Exception $exception) {
Log::info("Failed to use avatar image from LDAP data for user id {$user->id}");
}
}
}

223
app/Access/LoginService.php Normal file
View File

@@ -0,0 +1,223 @@
<?php
namespace BookStack\Access;
use BookStack\Access\Mfa\MfaSession;
use BookStack\Activity\ActivityType;
use BookStack\Exceptions\LoginAttemptException;
use BookStack\Exceptions\LoginAttemptInvalidUserException;
use BookStack\Exceptions\StoppedAuthenticationException;
use BookStack\Facades\Activity;
use BookStack\Facades\Theme;
use BookStack\Permissions\Permission;
use BookStack\Theming\ThemeEvents;
use BookStack\Users\Models\User;
use Exception;
class LoginService
{
protected const LAST_LOGIN_ATTEMPTED_SESSION_KEY = 'auth-login-last-attempted';
public function __construct(
protected MfaSession $mfaSession,
protected EmailConfirmationService $emailConfirmationService,
protected SocialDriverManager $socialDriverManager,
) {
}
/**
* Log the given user into the system.
* Will start a login of the given user but will prevent if there's
* a reason to (MFA or Unconfirmed Email).
* Returns a boolean to indicate the current login result.
*
* @throws StoppedAuthenticationException|LoginAttemptInvalidUserException
*/
public function login(User $user, string $method, bool $remember = false): void
{
if ($user->isGuest()) {
throw new LoginAttemptInvalidUserException('Login not allowed for guest user');
}
if ($this->awaitingEmailConfirmation($user) || $this->needsMfaVerification($user)) {
$this->setLastLoginAttemptedForUser($user, $method, $remember);
throw new StoppedAuthenticationException($user, $this);
}
$this->clearLastLoginAttempted();
auth()->login($user, $remember);
Activity::add(ActivityType::AUTH_LOGIN, "{$method}; {$user->logDescriptor()}");
Theme::dispatch(ThemeEvents::AUTH_LOGIN, $method, $user);
// Authenticate on all session guards if a likely admin
if ($user->can(Permission::UsersManage) && $user->can(Permission::UserRolesManage)) {
$guards = ['standard', 'ldap', 'saml2', 'oidc'];
foreach ($guards as $guard) {
auth($guard)->login($user);
}
}
}
/**
* Reattempt a system login after a previous stopped attempt.
*
* @throws Exception
*/
public function reattemptLoginFor(User $user): void
{
if ($user->id !== ($this->getLastLoginAttemptUser()->id ?? null)) {
throw new Exception('Login reattempt user does align with current session state');
}
$lastLoginDetails = $this->getLastLoginAttemptDetails();
$this->login($user, $lastLoginDetails['method'], $lastLoginDetails['remember'] ?? false);
}
/**
* Get the last user that was attempted to be logged in.
* Only exists if the last login attempt had correct credentials
* but had been prevented by a secondary factor.
*/
public function getLastLoginAttemptUser(): ?User
{
$id = $this->getLastLoginAttemptDetails()['user_id'];
return User::query()->where('id', '=', $id)->first();
}
/**
* Get the details of the last login attempt.
* Checks upon a ttl of about 1 hour since that last attempted login.
*
* @return array{user_id: ?string, method: ?string, remember: bool}
*/
protected function getLastLoginAttemptDetails(): array
{
$value = session()->get(self::LAST_LOGIN_ATTEMPTED_SESSION_KEY);
if (!$value) {
return ['user_id' => null, 'method' => null, 'remember' => false];
}
[$id, $method, $remember, $time] = explode(':', $value);
$hourAgo = time() - (60 * 60);
if ($time < $hourAgo) {
$this->clearLastLoginAttempted();
return ['user_id' => null, 'method' => null, 'remember' => false];
}
return ['user_id' => $id, 'method' => $method, 'remember' => boolval($remember)];
}
/**
* Set the last login-attempted user.
* Must be only used when credentials are correct and a login could be
* achieved, but a secondary factor has stopped the login.
*/
protected function setLastLoginAttemptedForUser(User $user, string $method, bool $remember): void
{
session()->put(
self::LAST_LOGIN_ATTEMPTED_SESSION_KEY,
implode(':', [$user->id, $method, $remember, time()])
);
}
/**
* Clear the last login attempted session value.
*/
protected function clearLastLoginAttempted(): void
{
session()->remove(self::LAST_LOGIN_ATTEMPTED_SESSION_KEY);
}
/**
* Check if MFA verification is needed.
*/
public function needsMfaVerification(User $user): bool
{
return !$this->mfaSession->isVerifiedForUser($user) && $this->mfaSession->isRequiredForUser($user);
}
/**
* Check if the given user is awaiting email confirmation.
*/
public function awaitingEmailConfirmation(User $user): bool
{
return $this->emailConfirmationService->confirmationRequired() && !$user->email_confirmed;
}
/**
* Attempt the login of a user using the given credentials.
* Meant to mirror Laravel's default guard 'attempt' method
* but in a manner that always routes through our login system.
* May interrupt the flow if extra authentication requirements are imposed.
*
* @throws StoppedAuthenticationException
* @throws LoginAttemptException
*/
public function attempt(array $credentials, string $method, bool $remember = false): bool
{
if ($this->areCredentialsForGuest($credentials)) {
return false;
}
$result = auth()->attempt($credentials, $remember);
if ($result) {
$user = auth()->user();
auth()->logout();
try {
$this->login($user, $method, $remember);
} catch (LoginAttemptInvalidUserException $e) {
// Catch and return false for non-login accounts
// so it looks like a normal invalid login.
return false;
}
}
return $result;
}
/**
* Check if the given credentials are likely for the system guest account.
*/
protected function areCredentialsForGuest(array $credentials): bool
{
if (isset($credentials['email'])) {
return User::query()->where('email', '=', $credentials['email'])
->where('system_name', '=', 'public')
->exists();
}
return false;
}
/**
* Logs the current user out of the application.
* Returns an app post-redirect path.
*/
public function logout(): string
{
auth()->logout();
session()->invalidate();
session()->regenerateToken();
return $this->shouldAutoInitiate() ? '/login?prevent_auto_init=true' : '/';
}
/**
* Check if login auto-initiate should be active based upon authentication config.
*/
public function shouldAutoInitiate(): bool
{
$autoRedirect = config('auth.auto_initiate');
if (!$autoRedirect) {
return false;
}
$socialDrivers = $this->socialDriverManager->getActive();
$authMethod = config('auth.method');
return count($socialDrivers) === 0 && in_array($authMethod, ['oidc', 'saml2']);
}
}

View File

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

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,27 @@
<?php
namespace BookStack\Access\Mfa;
use Closure;
use Illuminate\Contracts\Validation\ValidationRule;
class TotpValidationRule implements ValidationRule
{
/**
* Create a new rule instance.
* Takes the TOTP secret that must be system provided, not user provided.
*/
public function __construct(
protected string $secret,
protected TotpService $totpService,
) {
}
public function validate(string $attribute, mixed $value, Closure $fail): void
{
$passes = $this->totpService->verifyCode($value, $this->secret);
if (!$passes) {
$fail(trans('validation.totp'));
}
}
}

View File

@@ -0,0 +1,26 @@
<?php
namespace BookStack\Access\Notifications;
use BookStack\App\MailNotification;
use BookStack\Users\Models\User;
use Illuminate\Notifications\Messages\MailMessage;
class ConfirmEmailNotification extends MailNotification
{
public function __construct(
public string $token
) {
}
public function toMail(User $notifiable): MailMessage
{
$appName = ['appName' => setting('app-name')];
return $this->newMailMessage()
->subject(trans('auth.email_confirm_subject', $appName))
->greeting(trans('auth.email_confirm_greeting', $appName))
->line(trans('auth.email_confirm_text'))
->action(trans('auth.email_confirm_action'), url('/register/confirm/' . $this->token));
}
}

View File

@@ -0,0 +1,24 @@
<?php
namespace BookStack\Access\Notifications;
use BookStack\App\MailNotification;
use BookStack\Users\Models\User;
use Illuminate\Notifications\Messages\MailMessage;
class ResetPasswordNotification extends MailNotification
{
public function __construct(
public string $token
) {
}
public function toMail(User $notifiable): MailMessage
{
return $this->newMailMessage()
->subject(trans('auth.email_reset_subject', ['appName' => setting('app-name')]))
->line(trans('auth.email_reset_text'))
->action(trans('auth.reset_password'), url('password/reset/' . $this->token))
->line(trans('auth.email_reset_not_requested'));
}
}

View File

@@ -0,0 +1,27 @@
<?php
namespace BookStack\Access\Notifications;
use BookStack\App\MailNotification;
use BookStack\Users\Models\User;
use Illuminate\Notifications\Messages\MailMessage;
class UserInviteNotification extends MailNotification
{
public function __construct(
public string $token
) {
}
public function toMail(User $notifiable): MailMessage
{
$appName = ['appName' => setting('app-name')];
$locale = $notifiable->getLocale();
return $this->newMailMessage($locale)
->subject($locale->trans('auth.user_invite_email_subject', $appName))
->greeting($locale->trans('auth.user_invite_email_greeting', $appName))
->line($locale->trans('auth.user_invite_email_text'))
->action($locale->trans('auth.user_invite_email_action'), url('/register/invite/' . $this->token));
}
}

View File

@@ -0,0 +1,53 @@
<?php
namespace BookStack\Access\Oidc;
use InvalidArgumentException;
use League\OAuth2\Client\Token\AccessToken;
class OidcAccessToken extends AccessToken
{
/**
* Constructs an access token.
*
* @param array $options An array of options returned by the service provider
* in the access token request. The `access_token` option is required.
*
* @throws InvalidArgumentException if `access_token` is not provided in `$options`.
*/
public function __construct(array $options = [])
{
parent::__construct($options);
$this->validate($options);
}
/**
* Validate this access token response for OIDC.
* As per https://openid.net/specs/openid-connect-basic-1_0.html#TokenOK.
*/
private function validate(array $options): void
{
// access_token: REQUIRED. Access Token for the UserInfo Endpoint.
// Performed on the extended class
// token_type: REQUIRED. OAuth 2.0 Token Type value. The value MUST be Bearer, as specified in OAuth 2.0
// Bearer Token Usage [RFC6750], for Clients using this subset.
// Note that the token_type value is case-insensitive.
if (strtolower(($options['token_type'] ?? '')) !== 'bearer') {
throw new InvalidArgumentException('The response token type MUST be "Bearer"');
}
// id_token: REQUIRED. ID Token.
if (empty($options['id_token'])) {
throw new InvalidArgumentException('An "id_token" property must be provided');
}
}
/**
* Get the id token value from this access token response.
*/
public function getIdToken(): string
{
return $this->getValues()['id_token'];
}
}

View File

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

View File

@@ -0,0 +1,89 @@
<?php
namespace BookStack\Access\Oidc;
class OidcIdToken extends OidcJwtWithClaims implements ProvidesClaims
{
/**
* Validate all possible parts of the id token.
*
* @throws OidcInvalidTokenException
*/
public function validate(string $clientId): bool
{
parent::validateCommonTokenDetails($clientId);
$this->validateTokenClaims($clientId);
return true;
}
/**
* Validate the claims of the token.
* As per https://openid.net/specs/openid-connect-basic-1_0.html#IDTokenValidation.
*
* @throws OidcInvalidTokenException
*/
protected function validateTokenClaims(string $clientId): void
{
// 1. The Issuer Identifier for the OpenID Provider (which is typically obtained during Discovery)
// MUST exactly match the value of the iss (issuer) Claim.
// Already done in parent.
// 2. The Client MUST validate that the aud (audience) Claim contains its client_id value registered
// at the Issuer identified by the iss (issuer) Claim as an audience. The ID Token MUST be rejected
// if the ID Token does not list the Client as a valid audience, or if it contains additional
// audiences not trusted by the Client.
// Partially done in parent.
$aud = is_string($this->payload['aud']) ? [$this->payload['aud']] : $this->payload['aud'];
if (count($aud) !== 1) {
throw new OidcInvalidTokenException('Token audience value has ' . count($aud) . ' values, Expected 1');
}
// 3. If the ID Token contains multiple audiences, the Client SHOULD verify that an azp Claim is present.
// NOTE: Addressed by enforcing a count of 1 above.
// 4. If an azp (authorized party) Claim is present, the Client SHOULD verify that its client_id
// is the Claim Value.
if (isset($this->payload['azp']) && $this->payload['azp'] !== $clientId) {
throw new OidcInvalidTokenException('Token authorized party exists but does not match the expected client_id');
}
// 5. The current time MUST be before the time represented by the exp Claim
// (possibly allowing for some small leeway to account for clock skew).
if (empty($this->payload['exp'])) {
throw new OidcInvalidTokenException('Missing token expiration time value');
}
$skewSeconds = 120;
$now = time();
if ($now >= (intval($this->payload['exp']) + $skewSeconds)) {
throw new OidcInvalidTokenException('Token has expired');
}
// 6. The iat Claim can be used to reject tokens that were issued too far away from the current time,
// limiting the amount of time that nonces need to be stored to prevent attacks.
// The acceptable range is Client specific.
if (empty($this->payload['iat'])) {
throw new OidcInvalidTokenException('Missing token issued at time value');
}
$dayAgo = time() - 86400;
$iat = intval($this->payload['iat']);
if ($iat > ($now + $skewSeconds) || $iat < $dayAgo) {
throw new OidcInvalidTokenException('Token issue at time is not recent or is invalid');
}
// 7. If the acr Claim was requested, the Client SHOULD check that the asserted Claim Value is appropriate.
// The meaning and processing of acr Claim Values is out of scope for this document.
// NOTE: Not used for our case here. acr is not requested.
// 8. When a max_age request is made, the Client SHOULD check the auth_time Claim value and request
// re-authentication if it determines too much time has elapsed since the last End-User authentication.
// NOTE: Not used for our case here. A max_age request is not made.
// Custom: Ensure the "sub" (Subject) Claim exists and has a value.
if (empty($this->payload['sub'])) {
throw new OidcInvalidTokenException('Missing token subject value');
}
}
}

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,118 @@
<?php
namespace BookStack\Access\Oidc;
use phpseclib3\Crypt\Common\PublicKey;
use phpseclib3\Crypt\PublicKeyLoader;
use phpseclib3\Crypt\RSA;
use phpseclib3\Math\BigInteger;
class OidcJwtSigningKey
{
/**
* @var PublicKey
*/
protected $key;
/**
* Can be created either from a JWK parameter array or local file path to load a certificate from.
* Examples:
* 'file:///var/www/cert.pem'
* ['kty' => 'RSA', 'alg' => 'RS256', 'n' => 'abc123...'].
*
* @param array|string $jwkOrKeyPath
*
* @throws OidcInvalidKeyException
*/
public function __construct($jwkOrKeyPath)
{
if (is_array($jwkOrKeyPath)) {
$this->loadFromJwkArray($jwkOrKeyPath);
} elseif (is_string($jwkOrKeyPath) && strpos($jwkOrKeyPath, 'file://') === 0) {
$this->loadFromPath($jwkOrKeyPath);
} else {
throw new OidcInvalidKeyException('Unexpected type of key value provided');
}
}
/**
* @throws OidcInvalidKeyException
*/
protected function loadFromPath(string $path)
{
try {
$key = PublicKeyLoader::load(
file_get_contents($path)
);
} catch (\Exception $exception) {
throw new OidcInvalidKeyException("Failed to load key from file path with error: {$exception->getMessage()}");
}
if (!$key instanceof RSA) {
throw new OidcInvalidKeyException('Key loaded from file path is not an RSA key as expected');
}
$this->key = $key->withPadding(RSA::SIGNATURE_PKCS1);
}
/**
* @throws OidcInvalidKeyException
*/
protected function loadFromJwkArray(array $jwk)
{
// '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}");
}
// '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']}");
}
if (empty($jwk['e'])) {
throw new OidcInvalidKeyException('An "e" parameter on the provided key is expected');
}
if (empty($jwk['n'])) {
throw new OidcInvalidKeyException('A "n" parameter on the provided key is expected');
}
$n = strtr($jwk['n'] ?? '', '-_', '+/');
try {
$key = PublicKeyLoader::load([
'e' => new BigInteger(base64_decode($jwk['e']), 256),
'n' => new BigInteger(base64_decode($n), 256),
]);
} catch (\Exception $exception) {
throw new OidcInvalidKeyException("Failed to load key from JWK parameters with error: {$exception->getMessage()}");
}
if (!$key instanceof RSA) {
throw new OidcInvalidKeyException('Key loaded from file path is not an RSA key as expected');
}
$this->key = $key->withPadding(RSA::SIGNATURE_PKCS1);
}
/**
* Use this key to sign the given content and return the signature.
*/
public function verify(string $content, string $signature): bool
{
return $this->key->verify($content, $signature);
}
/**
* Convert the key to a PEM encoded key string.
*/
public function toPem(): string
{
return $this->key->toString('PKCS8');
}
}

View File

@@ -0,0 +1,174 @@
<?php
namespace BookStack\Access\Oidc;
class OidcJwtWithClaims implements ProvidesClaims
{
protected array $header;
protected array $payload;
protected string $signature;
protected string $issuer;
protected array $tokenParts = [];
/**
* @var array[]|string[]
*/
protected array $keys;
public function __construct(string $token, string $issuer, array $keys)
{
$this->keys = $keys;
$this->issuer = $issuer;
$this->parse($token);
}
/**
* Parse the token content into its components.
*/
protected function parse(string $token): void
{
$this->tokenParts = explode('.', $token);
$this->header = $this->parseEncodedTokenPart($this->tokenParts[0]);
$this->payload = $this->parseEncodedTokenPart($this->tokenParts[1] ?? '');
$this->signature = $this->base64UrlDecode($this->tokenParts[2] ?? '') ?: '';
}
/**
* Parse a Base64-JSON encoded token part.
* Returns the data as a key-value array or empty array upon error.
*/
protected function parseEncodedTokenPart(string $part): array
{
$json = $this->base64UrlDecode($part) ?: '{}';
$decoded = json_decode($json, true);
return is_array($decoded) ? $decoded : [];
}
/**
* Base64URL decode. Needs some character conversions to be compatible
* with PHP's default base64 handling.
*/
protected function base64UrlDecode(string $encoded): string
{
return base64_decode(strtr($encoded, '-_', '+/'));
}
/**
* Validate common parts of OIDC JWT tokens.
*
* @throws OidcInvalidTokenException
*/
public function validateCommonTokenDetails(string $clientId): bool
{
$this->validateTokenStructure();
$this->validateTokenSignature();
$this->validateCommonClaims($clientId);
return true;
}
/**
* Fetch a specific claim from this token.
* Returns null if it is null or does not exist.
*/
public function getClaim(string $claim): mixed
{
return $this->payload[$claim] ?? null;
}
/**
* Get all returned claims within the token.
*/
public function getAllClaims(): array
{
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.
*
* @throws OidcInvalidTokenException
*/
protected function validateTokenStructure(): void
{
foreach (['header', 'payload'] as $prop) {
if (empty($this->$prop) || !is_array($this->$prop)) {
throw new OidcInvalidTokenException("Could not parse out a valid {$prop} within the provided token");
}
}
if (empty($this->signature) || !is_string($this->signature)) {
throw new OidcInvalidTokenException('Could not parse out a valid signature within the provided token');
}
}
/**
* Validate the signature of the given token and ensure it validates against the provided key.
*
* @throws OidcInvalidTokenException
*/
protected function validateTokenSignature(): void
{
if ($this->header['alg'] !== 'RS256') {
throw new OidcInvalidTokenException("Only RS256 signature validation is supported. Token reports using {$this->header['alg']}");
}
$parsedKeys = array_map(function ($key) {
try {
return new OidcJwtSigningKey($key);
} catch (OidcInvalidKeyException $e) {
throw new OidcInvalidTokenException('Failed to read signing key with error: ' . $e->getMessage());
}
}, $this->keys);
$parsedKeys = array_filter($parsedKeys);
$contentToSign = $this->tokenParts[0] . '.' . $this->tokenParts[1];
/** @var OidcJwtSigningKey $parsedKey */
foreach ($parsedKeys as $parsedKey) {
if ($parsedKey->verify($contentToSign, $this->signature)) {
return;
}
}
throw new OidcInvalidTokenException('Token signature could not be validated using the provided keys');
}
/**
* Validate common claims for OIDC JWT tokens.
* As per https://openid.net/specs/openid-connect-basic-1_0.html#IDTokenValidation
* and https://openid.net/specs/openid-connect-core-1_0.html#UserInfoResponse
*
* @throws OidcInvalidTokenException
*/
protected function validateCommonClaims(string $clientId): void
{
// 1. The Issuer Identifier for the OpenID Provider (which is typically obtained during Discovery)
// MUST exactly match the value of the iss (issuer) Claim.
if (empty($this->payload['iss']) || $this->issuer !== $this->payload['iss']) {
throw new OidcInvalidTokenException('Missing or non-matching token issuer value');
}
// 2. The Client MUST validate that the aud (audience) Claim contains its client_id value registered
// at the Issuer identified by the iss (issuer) Claim as an audience. The ID Token MUST be rejected
// if the ID Token does not list the Client as a valid audience.
if (empty($this->payload['aud'])) {
throw new OidcInvalidTokenException('Missing token audience value');
}
$aud = is_string($this->payload['aud']) ? [$this->payload['aud']] : $this->payload['aud'];
if (!in_array($clientId, $aud, true)) {
throw new OidcInvalidTokenException('Token audience value did not match the expected client_id');
}
}
}

View File

@@ -0,0 +1,127 @@
<?php
namespace BookStack\Access\Oidc;
use League\OAuth2\Client\Grant\AbstractGrant;
use League\OAuth2\Client\Provider\AbstractProvider;
use League\OAuth2\Client\Provider\Exception\IdentityProviderException;
use League\OAuth2\Client\Provider\GenericResourceOwner;
use League\OAuth2\Client\Provider\ResourceOwnerInterface;
use League\OAuth2\Client\Token\AccessToken;
use League\OAuth2\Client\Tool\BearerAuthorizationTrait;
use Psr\Http\Message\ResponseInterface;
/**
* Extended OAuth2Provider for using with OIDC.
* Credit to the https://github.com/steverhoades/oauth2-openid-connect-client
* project for the idea of extending a League\OAuth2 client for this use-case.
*/
class OidcOAuthProvider extends AbstractProvider
{
use BearerAuthorizationTrait;
protected string $authorizationEndpoint;
protected string $tokenEndpoint;
/**
* Scopes to use for the OIDC authorization call.
*/
protected array $scopes = ['openid', 'profile', 'email'];
/**
* Returns the base URL for authorizing a client.
*/
public function getBaseAuthorizationUrl(): string
{
return $this->authorizationEndpoint;
}
/**
* Returns the base URL for requesting an access token.
*/
public function getBaseAccessTokenUrl(array $params): string
{
return $this->tokenEndpoint;
}
/**
* Returns the URL for requesting the resource owner's details.
*/
public function getResourceOwnerDetailsUrl(AccessToken $token): string
{
return '';
}
/**
* Add another 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.
*
* This should only be the scopes that are required to request the details
* of the resource owner, rather than all the available scopes.
*/
protected function getDefaultScopes(): array
{
return $this->scopes;
}
/**
* Returns the string that should be used to separate scopes when building
* the URL for requesting an access token.
*/
protected function getScopeSeparator(): string
{
return ' ';
}
/**
* Checks a provider response for errors.
* @throws IdentityProviderException
*/
protected function checkResponse(ResponseInterface $response, $data): void
{
if ($response->getStatusCode() >= 400 || isset($data['error'])) {
throw new IdentityProviderException(
$data['error'] ?? $response->getReasonPhrase(),
$response->getStatusCode(),
(string) $response->getBody()
);
}
}
/**
* Generates a resource owner object from a successful resource owner
* details request.
*/
protected function createResourceOwner(array $response, AccessToken $token): ResourceOwnerInterface
{
return new GenericResourceOwner($response, '');
}
/**
* Creates an access token from a response.
*
* The grant that was used to fetch the response can be used to provide
* additional context.
*/
protected function createAccessToken(array $response, AbstractGrant $grant): OidcAccessToken
{
return new OidcAccessToken($response);
}
/**
* Get the method used for PKCE code verifier hashing, which is passed
* in the "code_challenge_method" parameter in the authorization request.
*/
protected function getPkceMethod(): string
{
return static::PKCE_METHOD_S256;
}
}

View File

@@ -0,0 +1,200 @@
<?php
namespace BookStack\Access\Oidc;
use GuzzleHttp\Psr7\Request;
use Illuminate\Contracts\Cache\Repository;
use InvalidArgumentException;
use Psr\Http\Client\ClientExceptionInterface;
use Psr\Http\Client\ClientInterface;
/**
* OpenIdConnectProviderSettings
* Acts as a DTO for settings used within the oidc request and token handling.
* Performs auto-discovery upon request.
*/
class OidcProviderSettings
{
public string $issuer;
public string $clientId;
public string $clientSecret;
public ?string $authorizationEndpoint;
public ?string $tokenEndpoint;
public ?string $endSessionEndpoint;
public ?string $userinfoEndpoint;
/**
* @var string[]|array[]
*/
public ?array $keys = [];
public function __construct(array $settings)
{
$this->applySettingsFromArray($settings);
$this->validateInitial();
}
/**
* Apply an array of settings to populate setting properties within this class.
*/
protected function applySettingsFromArray(array $settingsArray): void
{
foreach ($settingsArray as $key => $value) {
if (property_exists($this, $key)) {
$this->$key = $value;
}
}
}
/**
* Validate any core, required properties have been set.
*
* @throws InvalidArgumentException
*/
protected function validateInitial(): void
{
$required = ['clientId', 'clientSecret', 'issuer'];
foreach ($required as $prop) {
if (empty($this->$prop)) {
throw new InvalidArgumentException("Missing required configuration \"{$prop}\" value");
}
}
if (!str_starts_with($this->issuer, 'https://')) {
throw new InvalidArgumentException('Issuer value must start with https://');
}
}
/**
* Perform a full validation on these settings.
*
* @throws InvalidArgumentException
*/
public function validate(): void
{
$this->validateInitial();
$required = ['keys', 'tokenEndpoint', 'authorizationEndpoint'];
foreach ($required as $prop) {
if (empty($this->$prop)) {
throw new InvalidArgumentException("Missing required configuration \"{$prop}\" value");
}
}
$endpointProperties = ['tokenEndpoint', 'authorizationEndpoint', 'userinfoEndpoint'];
foreach ($endpointProperties as $prop) {
if (is_string($this->$prop) && !str_starts_with($this->$prop, 'https://')) {
throw new InvalidArgumentException("Endpoint value for \"{$prop}\" must start with https://");
}
}
}
/**
* Discover and autoload settings from the configured issuer.
*
* @throws OidcIssuerDiscoveryException
*/
public function discoverFromIssuer(ClientInterface $httpClient, Repository $cache, int $cacheMinutes): void
{
try {
$cacheKey = 'oidc-discovery::' . $this->issuer;
$discoveredSettings = $cache->remember($cacheKey, $cacheMinutes * 60, function () use ($httpClient) {
return $this->loadSettingsFromIssuerDiscovery($httpClient);
});
$this->applySettingsFromArray($discoveredSettings);
} catch (ClientExceptionInterface $exception) {
throw new OidcIssuerDiscoveryException("HTTP request failed during discovery with error: {$exception->getMessage()}");
}
}
/**
* @throws OidcIssuerDiscoveryException
* @throws ClientExceptionInterface
*/
protected function loadSettingsFromIssuerDiscovery(ClientInterface $httpClient): array
{
$issuerUrl = rtrim($this->issuer, '/') . '/.well-known/openid-configuration';
$request = new Request('GET', $issuerUrl);
$response = $httpClient->sendRequest($request);
$result = json_decode($response->getBody()->getContents(), true);
if (empty($result) || !is_array($result)) {
throw new OidcIssuerDiscoveryException("Error discovering provider settings from issuer at URL {$issuerUrl}");
}
if ($result['issuer'] !== $this->issuer) {
throw new OidcIssuerDiscoveryException('Unexpected issuer value found on discovery response');
}
$discoveredSettings = [];
if (!empty($result['authorization_endpoint'])) {
$discoveredSettings['authorizationEndpoint'] = $result['authorization_endpoint'];
}
if (!empty($result['token_endpoint'])) {
$discoveredSettings['tokenEndpoint'] = $result['token_endpoint'];
}
if (!empty($result['userinfo_endpoint'])) {
$discoveredSettings['userinfoEndpoint'] = $result['userinfo_endpoint'];
}
if (!empty($result['jwks_uri'])) {
$keys = $this->loadKeysFromUri($result['jwks_uri'], $httpClient);
$discoveredSettings['keys'] = $this->filterKeys($keys);
}
if (!empty($result['end_session_endpoint'])) {
$discoveredSettings['endSessionEndpoint'] = $result['end_session_endpoint'];
}
return $discoveredSettings;
}
/**
* Filter the given JWK keys down to just those we support.
*/
protected function filterKeys(array $keys): array
{
return array_filter($keys, function (array $key) {
$alg = $key['alg'] ?? 'RS256';
$use = $key['use'] ?? 'sig';
return $key['kty'] === 'RSA' && $use === 'sig' && $alg === 'RS256';
});
}
/**
* Return an array of jwks as PHP key=>value arrays.
*
* @throws ClientExceptionInterface
* @throws OidcIssuerDiscoveryException
*/
protected function loadKeysFromUri(string $uri, ClientInterface $httpClient): array
{
$request = new Request('GET', $uri);
$response = $httpClient->sendRequest($request);
$result = json_decode($response->getBody()->getContents(), true);
if (empty($result) || !is_array($result) || !isset($result['keys'])) {
throw new OidcIssuerDiscoveryException('Error reading keys from issuer jwks_uri');
}
return $result['keys'];
}
/**
* Get the settings needed by an OAuth provider, as a key=>value array.
*/
public function arrayForOAuthProvider(): array
{
$settingKeys = ['clientId', 'clientSecret', 'authorizationEndpoint', 'tokenEndpoint', 'userinfoEndpoint'];
$settings = [];
foreach ($settingKeys as $setting) {
$settings[$setting] = $this->$setting;
}
return $settings;
}
}

View File

@@ -0,0 +1,319 @@
<?php
namespace BookStack\Access\Oidc;
use BookStack\Access\GroupSyncService;
use BookStack\Access\LoginService;
use BookStack\Access\RegistrationService;
use BookStack\Exceptions\JsonDebugException;
use BookStack\Exceptions\StoppedAuthenticationException;
use BookStack\Exceptions\UserRegistrationException;
use BookStack\Facades\Theme;
use BookStack\Http\HttpRequestService;
use BookStack\Theming\ThemeEvents;
use BookStack\Uploads\UserAvatars;
use BookStack\Users\Models\User;
use Illuminate\Support\Facades\Cache;
use League\OAuth2\Client\OptionProvider\HttpBasicAuthOptionProvider;
use League\OAuth2\Client\Provider\Exception\IdentityProviderException;
/**
* Class OpenIdConnectService
* Handles any app-specific OIDC tasks.
*/
class OidcService
{
public function __construct(
protected RegistrationService $registrationService,
protected LoginService $loginService,
protected HttpRequestService $http,
protected GroupSyncService $groupService,
protected UserAvatars $userAvatars
) {
}
/**
* Initiate an authorization flow.
* Provides back an authorize redirect URL, in addition to other
* details which may be required for the auth flow.
*
* @throws OidcException
*
* @return array{url: string, state: string}
*/
public function login(): array
{
$settings = $this->getProviderSettings();
$provider = $this->getProvider($settings);
$url = $provider->getAuthorizationUrl();
session()->put('oidc_pkce_code', $provider->getPkceCode() ?? '');
return [
'url' => $url,
'state' => $provider->getState(),
];
}
/**
* Process the Authorization response from the authorization server and
* 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 JsonDebugException
* @throws OidcException
* @throws StoppedAuthenticationException
* @throws IdentityProviderException
*/
public function processAuthorizeResponse(?string $authorizationCode): User
{
$settings = $this->getProviderSettings();
$provider = $this->getProvider($settings);
// Set PKCE code flashed at login
$pkceCode = session()->pull('oidc_pkce_code', '');
$provider->setPkceCode($pkceCode);
// Try to exchange authorization code for access token
$accessToken = $provider->getAccessToken('authorization_code', [
'code' => $authorizationCode,
]);
return $this->processAccessTokenCallback($accessToken, $settings);
}
/**
* @throws OidcException
*/
protected function getProviderSettings(): OidcProviderSettings
{
$config = $this->config();
$settings = new OidcProviderSettings([
'issuer' => $config['issuer'],
'clientId' => $config['client_id'],
'clientSecret' => $config['client_secret'],
'authorizationEndpoint' => $config['authorization_endpoint'],
'tokenEndpoint' => $config['token_endpoint'],
'endSessionEndpoint' => is_string($config['end_session_endpoint']) ? $config['end_session_endpoint'] : null,
'userinfoEndpoint' => $config['userinfo_endpoint'],
]);
// Use keys if configured
if (!empty($config['jwt_public_key'])) {
$settings->keys = [$config['jwt_public_key']];
}
// Run discovery
if ($config['discover'] ?? false) {
try {
$settings->discoverFromIssuer($this->http->buildClient(5), Cache::store(null), 15);
} catch (OidcIssuerDiscoveryException $exception) {
throw new OidcException('OIDC Discovery Error: ' . $exception->getMessage());
}
}
// Prevent use of RP-initiated logout if specifically disabled
// Or force use of a URL if specifically set.
if ($config['end_session_endpoint'] === false) {
$settings->endSessionEndpoint = null;
} else if (is_string($config['end_session_endpoint'])) {
$settings->endSessionEndpoint = $config['end_session_endpoint'];
}
$settings->validate();
return $settings;
}
/**
* Load the underlying OpenID Connect Provider.
*/
protected function getProvider(OidcProviderSettings $settings): OidcOAuthProvider
{
$provider = new OidcOAuthProvider([
...$settings->arrayForOAuthProvider(),
'redirectUri' => url('/oidc/callback'),
], [
'httpClient' => $this->http->buildClient(5),
'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);
}
/**
* Processes a received access token for a user. Login the user when
* they exist, optionally registering them automatically.
*
* @throws OidcException
* @throws JsonDebugException
* @throws StoppedAuthenticationException
*/
protected function processAccessTokenCallback(OidcAccessToken $accessToken, OidcProviderSettings $settings): User
{
$idTokenText = $accessToken->getIdToken();
$idToken = new OidcIdToken(
$idTokenText,
$settings->issuer,
$settings->keys,
);
session()->put("oidc_id_token", $idTokenText);
$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());
}
try {
$idToken->validate($settings->clientId);
} catch (OidcInvalidTokenException $exception) {
throw new OidcException("ID token validation failed with error: {$exception->getMessage()}");
}
$userDetails = $this->getUserDetailsFromToken($idToken, $accessToken, $settings);
if (empty($userDetails->email)) {
throw new OidcException(trans('errors.oidc_no_email_address'));
}
if (empty($userDetails->name)) {
$userDetails->name = $userDetails->externalId;
}
$isLoggedIn = auth()->check();
if ($isLoggedIn) {
throw new OidcException(trans('errors.oidc_already_logged_in'));
}
try {
$user = $this->registrationService->findOrRegister(
$userDetails->name,
$userDetails->email,
$userDetails->externalId
);
} catch (UserRegistrationException $exception) {
throw new OidcException($exception->getMessage());
}
if ($this->config()['fetch_avatar'] && !$user->avatar()->exists() && $userDetails->picture) {
$this->userAvatars->assignToUserFromUrl($user, $userDetails->picture);
}
if ($this->shouldSyncGroups()) {
$detachExisting = $this->config()['remove_from_groups'];
$this->groupService->syncUserWithFoundGroups($user, $userDetails->groups ?? [], $detachExisting);
}
$this->loginService->login($user, 'oidc');
return $user;
}
/**
* @throws OidcException
*/
protected function getUserDetailsFromToken(OidcIdToken $idToken, OidcAccessToken $accessToken, OidcProviderSettings $settings): OidcUserDetails
{
$userDetails = new OidcUserDetails();
$userDetails->populate(
$idToken,
$this->config()['external_id_claim'],
$this->config()['display_name_claims'] ?? '',
$this->config()['groups_claim'] ?? ''
);
if (!$userDetails->isFullyPopulated($this->shouldSyncGroups()) && !empty($settings->userinfoEndpoint)) {
$provider = $this->getProvider($settings);
$request = $provider->getAuthenticatedRequest('GET', $settings->userinfoEndpoint, $accessToken->getToken());
$response = new OidcUserinfoResponse(
$provider->getResponse($request),
$settings->issuer,
$settings->keys,
);
try {
$response->validate($idToken->getClaim('sub'), $settings->clientId);
} catch (OidcInvalidTokenException $exception) {
throw new OidcException("Userinfo endpoint response validation failed with error: {$exception->getMessage()}");
}
$userDetails->populate(
$response,
$this->config()['external_id_claim'],
$this->config()['display_name_claims'] ?? '',
$this->config()['groups_claim'] ?? ''
);
}
return $userDetails;
}
/**
* Get the OIDC config from the application.
*/
protected function config(): array
{
return config('oidc');
}
/**
* Check if groups should be synced.
*/
protected function shouldSyncGroups(): bool
{
return $this->config()['user_to_groups'] !== false;
}
/**
* Start the RP-initiated logout flow if active, otherwise start a standard logout flow.
* Returns a post-app-logout redirect URL.
* Reference: https://openid.net/specs/openid-connect-rpinitiated-1_0.html
* @throws OidcException
*/
public function logout(): string
{
$oidcToken = session()->pull("oidc_id_token");
$defaultLogoutUrl = url($this->loginService->logout());
$oidcSettings = $this->getProviderSettings();
if (!$oidcSettings->endSessionEndpoint) {
return $defaultLogoutUrl;
}
$endpointParams = [
'id_token_hint' => $oidcToken,
'post_logout_redirect_uri' => $defaultLogoutUrl,
];
$joiner = str_contains($oidcSettings->endSessionEndpoint, '?') ? '&' : '?';
return $oidcSettings->endSessionEndpoint . $joiner . http_build_query($endpointParams);
}
}

View File

@@ -0,0 +1,87 @@
<?php
namespace BookStack\Access\Oidc;
use Illuminate\Support\Arr;
class OidcUserDetails
{
public function __construct(
public ?string $externalId = null,
public ?string $email = null,
public ?string $name = null,
public ?array $groups = null,
public ?string $picture = null,
) {
}
/**
* Check if the user details are fully populated for our usage.
*/
public function isFullyPopulated(bool $groupSyncActive): bool
{
$hasEmpty = empty($this->externalId)
|| empty($this->email)
|| empty($this->name)
|| ($groupSyncActive && $this->groups === null);
return !$hasEmpty;
}
/**
* Populate user details from the given claim data.
*/
public function populate(
ProvidesClaims $claims,
string $idClaim,
string $displayNameClaims,
string $groupsClaim,
): void {
$this->externalId = $claims->getClaim($idClaim) ?? $this->externalId;
$this->email = $claims->getClaim('email') ?? $this->email;
$this->name = static::getUserDisplayName($displayNameClaims, $claims) ?? $this->name;
$this->groups = static::getUserGroups($groupsClaim, $claims) ?? $this->groups;
$this->picture = static::getPicture($claims) ?: $this->picture;
}
protected static function getUserDisplayName(string $displayNameClaims, ProvidesClaims $claims): string
{
$displayNameClaimParts = explode('|', $displayNameClaims);
$displayName = [];
foreach ($displayNameClaimParts as $claim) {
$component = $claims->getClaim(trim($claim)) ?? '';
if ($component !== '') {
$displayName[] = $component;
}
}
return implode(' ', $displayName);
}
protected static function getUserGroups(string $groupsClaim, ProvidesClaims $claims): ?array
{
if (empty($groupsClaim)) {
return null;
}
$groupsList = Arr::get($claims->getAllClaims(), $groupsClaim);
if (!is_array($groupsList)) {
return null;
}
return array_values(array_filter($groupsList, function ($val) {
return is_string($val);
}));
}
protected static function getPicture(ProvidesClaims $claims): ?string
{
$picture = $claims->getClaim('picture');
if (is_string($picture) && str_starts_with($picture, 'http')) {
return $picture;
}
return null;
}
}

View File

@@ -0,0 +1,69 @@
<?php
namespace BookStack\Access\Oidc;
use Psr\Http\Message\ResponseInterface;
class OidcUserinfoResponse implements ProvidesClaims
{
protected array $claims = [];
protected ?OidcJwtWithClaims $jwt = null;
public function __construct(ResponseInterface $response, string $issuer, array $keys)
{
$contentTypeHeaderValue = $response->getHeader('Content-Type')[0] ?? '';
$contentType = strtolower(trim(explode(';', $contentTypeHeaderValue, 2)[0]));
if ($contentType === 'application/json') {
$this->claims = json_decode($response->getBody()->getContents(), true);
}
if ($contentType === 'application/jwt') {
$this->jwt = new OidcJwtWithClaims($response->getBody()->getContents(), $issuer, $keys);
$this->claims = $this->jwt->getAllClaims();
}
}
/**
* @throws OidcInvalidTokenException
*/
public function validate(string $idTokenSub, string $clientId): bool
{
if (!is_null($this->jwt)) {
$this->jwt->validateCommonTokenDetails($clientId);
}
$sub = $this->getClaim('sub');
// Spec: v1.0 5.3.2: The sub (subject) Claim MUST always be returned in the UserInfo Response.
if (!is_string($sub) || empty($sub)) {
throw new OidcInvalidTokenException("No valid subject value found in userinfo data");
}
// Spec: v1.0 5.3.2: The sub Claim in the UserInfo Response MUST be verified to exactly match the sub Claim in the ID Token;
// if they do not match, the UserInfo Response values MUST NOT be used.
if ($idTokenSub !== $sub) {
throw new OidcInvalidTokenException("Subject value provided in the userinfo endpoint does not match the provided ID token value");
}
// Spec v1.0 5.3.4 Defines the following:
// Verify that the OP that responded was the intended OP through a TLS server certificate check, per RFC 6125 [RFC6125].
// This is effectively done as part of the HTTP request we're making through CURLOPT_SSL_VERIFYHOST on the request.
// If the Client has provided a userinfo_encrypted_response_alg parameter during Registration, decrypt the UserInfo Response using the keys specified during Registration.
// We don't currently support JWT encryption for OIDC
// If the response was signed, the Client SHOULD validate the signature according to JWS [JWS].
// This is done as part of the validateCommonClaims above.
return true;
}
public function getClaim(string $claim): mixed
{
return $this->claims[$claim] ?? null;
}
public function getAllClaims(): array
{
return $this->claims;
}
}

View File

@@ -0,0 +1,17 @@
<?php
namespace BookStack\Access\Oidc;
interface ProvidesClaims
{
/**
* Fetch a specific claim.
* Returns null if it is null or does not exist.
*/
public function getClaim(string $claim): mixed;
/**
* Get all contained claims.
*/
public function getAllClaims(): array;
}

View File

@@ -0,0 +1,149 @@
<?php
namespace BookStack\Access;
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;
class RegistrationService
{
public function __construct(
protected UserRepo $userRepo,
protected EmailConfirmationService $emailConfirmationService,
) {
}
/**
* Check if registrations are allowed in the app settings.
*
* @throws UserRegistrationException
*/
public function ensureRegistrationAllowed()
{
if (!$this->registrationAllowed()) {
throw new UserRegistrationException(trans('auth.registrations_disabled'), '/login');
}
}
/**
* Check if standard BookStack User registrations are currently allowed.
* Does not prevent external-auth based registration.
*/
protected function registrationAllowed(): bool
{
$authMethod = config('auth.method');
$authMethodsWithRegistration = ['standard'];
return in_array($authMethod, $authMethodsWithRegistration) && setting('registration-enabled');
}
/**
* Attempt to find a user in the system otherwise register them as a new
* user. For use with external auth systems since password is auto-generated.
*
* @throws UserRegistrationException
*/
public function findOrRegister(string $name, string $email, string $externalId): User
{
$user = User::query()
->where('external_auth_id', '=', $externalId)
->first();
if (is_null($user)) {
$userData = [
'name' => $name,
'email' => $email,
'password' => Str::random(32),
'external_auth_id' => $externalId,
];
$user = $this->registerUser($userData, null, false);
}
return $user;
}
/**
* The registrations flow for all users.
*
* @throws UserRegistrationException
*/
public function registerUser(array $userData, ?SocialAccount $socialAccount = null, bool $emailConfirmed = false): User
{
$userEmail = $userData['email'];
$authSystem = $socialAccount ? $socialAccount->driver : auth()->getDefaultDriver();
// Email restriction
$this->ensureEmailDomainAllowed($userEmail);
// Ensure user does not already exist
$alreadyUser = !is_null($this->userRepo->getByEmail($userEmail));
if ($alreadyUser) {
throw new UserRegistrationException(trans('errors.error_user_exists_different_creds', ['email' => $userEmail]), '/login');
}
/** @var ?bool $shouldRegister */
$shouldRegister = Theme::dispatch(ThemeEvents::AUTH_PRE_REGISTER, $authSystem, $userData);
if ($shouldRegister === false) {
throw new UserRegistrationException(trans('errors.auth_pre_register_theme_prevention'), '/login');
}
// Create the user
$newUser = $this->userRepo->createWithoutActivity($userData, $emailConfirmed);
$newUser->attachDefaultRole();
// Assign social account if given
if ($socialAccount) {
$newUser->socialAccounts()->save($socialAccount);
}
Activity::add(ActivityType::AUTH_REGISTER, $socialAccount ?? $newUser);
Theme::dispatch(ThemeEvents::AUTH_REGISTER, $authSystem, $newUser);
// Start email confirmation flow if required
if ($this->emailConfirmationService->confirmationRequired() && !$emailConfirmed) {
$newUser->save();
try {
$this->emailConfirmationService->sendConfirmation($newUser);
session()->flash('sent-email-confirmation', true);
} catch (Exception $e) {
$message = trans('auth.email_confirm_send_error');
throw new UserRegistrationException($message, '/register/confirm');
}
}
return $newUser;
}
/**
* Ensure that the given email meets any active email domain registration restrictions.
* Throws if restrictions are active and the email does not match an allowed domain.
*
* @throws UserRegistrationException
*/
protected function ensureEmailDomainAllowed(string $userEmail): void
{
$registrationRestrict = setting('registration-restrict');
if (!$registrationRestrict) {
return;
}
$restrictedEmailDomains = explode(',', str_replace(' ', '', $registrationRestrict));
$userEmailDomain = mb_substr(mb_strrchr($userEmail, '@'), 1);
if (!in_array($userEmailDomain, $restrictedEmailDomains)) {
$redirect = $this->registrationAllowed() ? '/register' : '/login';
throw new UserRegistrationException(trans('auth.registration_email_domain_invalid'), $redirect);
}
}
}

382
app/Access/Saml2Service.php Normal file
View File

@@ -0,0 +1,382 @@
<?php
namespace BookStack\Access;
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;
use OneLogin\Saml2\Error;
use OneLogin\Saml2\IdPMetadataParser;
use OneLogin\Saml2\ValidationError;
/**
* Class Saml2Service
* Handles any app-specific SAML tasks.
*/
class Saml2Service
{
protected array $config;
public function __construct(
protected RegistrationService $registrationService,
protected LoginService $loginService,
protected GroupSyncService $groupSyncService
) {
$this->config = config('saml2');
}
/**
* Initiate a login flow.
*
* @throws Error
*/
public function login(): array
{
$toolKit = $this->getToolkit();
$returnRoute = url('/saml2/acs');
return [
'url' => $toolKit->login($returnRoute, [], false, false, true),
'id' => $toolKit->getLastRequestID(),
];
}
/**
* Initiate a logout flow.
* Returns the SAML2 request ID, and the URL to redirect the user to.
*
* @throws Error
* @return array{url: string, id: ?string}
*/
public function logout(User $user): array
{
$toolKit = $this->getToolkit();
$sessionIndex = session()->get('saml2_session_index');
$returnUrl = url($this->loginService->logout());
try {
$url = $toolKit->logout(
$returnUrl,
[],
$user->email,
$sessionIndex,
true,
Constants::NAMEID_EMAIL_ADDRESS
);
$id = $toolKit->getLastRequestID();
} catch (Error $error) {
if ($error->getCode() !== Error::SAML_SINGLE_LOGOUT_NOT_SUPPORTED) {
throw $error;
}
$url = $returnUrl;
$id = null;
}
return ['url' => $url, 'id' => $id];
}
/**
* Process the ACS response from the idp and return the
* matching, or new if registration active, user matched to the idp.
* Returns null if not authenticated.
*
* @throws Error
* @throws SamlException
* @throws ValidationError
* @throws JsonDebugException
* @throws UserRegistrationException
*/
public function processAcsResponse(?string $requestId, string $samlResponse): ?User
{
// The SAML2 toolkit expects the response to be within the $_POST superglobal
// so we need to manually put it back there at this point.
$_POST['SAMLResponse'] = $samlResponse;
$toolkit = $this->getToolkit();
$toolkit->processResponse($requestId);
$errors = $toolkit->getErrors();
if (!empty($errors)) {
$reason = $toolkit->getLastErrorReason();
$message = 'Invalid ACS Response; Errors: ' . implode(', ', $errors);
$message .= $reason ? "; Reason: {$reason}" : '';
throw new Error($message);
}
if (!$toolkit->isAuthenticated()) {
return null;
}
$attrs = $toolkit->getAttributes();
$id = $toolkit->getNameId();
session()->put('saml2_session_index', $toolkit->getSessionIndex());
return $this->processLoginCallback($id, $attrs);
}
/**
* Process a response for the single logout service.
*
* @throws Error
*/
public function processSlsResponse(?string $requestId): string
{
$toolkit = $this->getToolkit();
// The $retrieveParametersFromServer in the call below will mean the library will take the query
// parameters, used for the response signing, from the raw $_SERVER['QUERY_STRING']
// value so that the exact encoding format is matched when checking the signature.
// This is primarily due to ADFS encoding query params with lowercase percent encoding while
// PHP (And most other sensible providers) standardise on uppercase.
/** @var ?string $samlRedirect */
$samlRedirect = $toolkit->processSLO(true, $requestId, true, null, true);
$errors = $toolkit->getErrors();
if (!empty($errors)) {
throw new Error(
'Invalid SLS Response: ' . implode(', ', $errors)
);
}
$defaultBookStackRedirect = $this->loginService->logout();
return $samlRedirect ?? $defaultBookStackRedirect;
}
/**
* Get the metadata for this service provider.
*
* @throws Error
*/
public function metadata(): string
{
$toolKit = $this->getToolkit(true);
$settings = $toolKit->getSettings();
$metadata = $settings->getSPMetadata();
$errors = $settings->validateMetadata($metadata);
if (!empty($errors)) {
throw new Error(
'Invalid SP metadata: ' . implode(', ', $errors),
Error::METADATA_SP_INVALID
);
}
return $metadata;
}
/**
* Load the underlying Onelogin SAML2 toolkit.
*
* @throws Error
* @throws Exception
*/
protected function getToolkit(bool $spOnly = false): Auth
{
$settings = $this->config['onelogin'];
$overrides = $this->config['onelogin_overrides'] ?? [];
if ($overrides && is_string($overrides)) {
$overrides = json_decode($overrides, true);
}
$metaDataSettings = [];
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, $spOnly);
}
/**
* Load dynamic service provider options required by the onelogin toolkit.
*/
protected function loadOneloginServiceProviderDetails(): array
{
$spDetails = [
'entityId' => url('/saml2/metadata'),
'assertionConsumerService' => [
'url' => url('/saml2/acs'),
],
'singleLogoutService' => [
'url' => url('/saml2/sls'),
],
];
return [
'baseurl' => url('/saml2'),
'sp' => $spDetails,
];
}
/**
* Check if groups should be synced.
*/
protected function shouldSyncGroups(): bool
{
return $this->config['user_to_groups'] !== false;
}
/**
* Calculate the display name.
*/
protected function getUserDisplayName(array $samlAttributes, string $defaultValue): string
{
$displayNameAttr = $this->config['display_name_attributes'];
$displayName = [];
foreach ($displayNameAttr as $dnAttr) {
$dnComponent = $this->getSamlResponseAttribute($samlAttributes, $dnAttr, null);
if ($dnComponent !== null) {
$displayName[] = $dnComponent;
}
}
if (count($displayName) == 0) {
$displayName = $defaultValue;
} else {
$displayName = implode(' ', $displayName);
}
return $displayName;
}
/**
* Get the value to use as the external id saved in BookStack
* used to link the user to an existing BookStack DB user.
*/
protected function getExternalId(array $samlAttributes, string $defaultValue)
{
$userNameAttr = $this->config['external_id_attribute'];
if ($userNameAttr === null) {
return $defaultValue;
}
return $this->getSamlResponseAttribute($samlAttributes, $userNameAttr, $defaultValue);
}
/**
* Extract the details of a user from a SAML response.
*
* @return array{external_id: string, name: string, email: string, saml_id: string}
*/
protected function getUserDetails(string $samlID, $samlAttributes): array
{
$emailAttr = $this->config['email_attribute'];
$externalId = $this->getExternalId($samlAttributes, $samlID);
$defaultEmail = filter_var($samlID, FILTER_VALIDATE_EMAIL) ? $samlID : null;
$email = $this->getSamlResponseAttribute($samlAttributes, $emailAttr, $defaultEmail);
return [
'external_id' => $externalId,
'name' => $this->getUserDisplayName($samlAttributes, $externalId),
'email' => $email,
'saml_id' => $samlID,
];
}
/**
* Get the groups a user is a part of from the SAML response.
*/
public function getUserGroups(array $samlAttributes): array
{
$groupsAttr = $this->config['group_attribute'];
$userGroups = $samlAttributes[$groupsAttr] ?? null;
if (!is_array($userGroups)) {
$userGroups = [];
}
return $userGroups;
}
/**
* For an array of strings, return a default for an empty array,
* a string for an array with one element and the full array for
* more than one element.
*/
protected function simplifyValue(array $data, $defaultValue)
{
switch (count($data)) {
case 0:
$data = $defaultValue;
break;
case 1:
$data = $data[0];
break;
}
return $data;
}
/**
* Get a property from an SAML response.
* Handles properties potentially being an array.
*/
protected function getSamlResponseAttribute(array $samlAttributes, string $propertyKey, $defaultValue)
{
if (isset($samlAttributes[$propertyKey])) {
return $this->simplifyValue($samlAttributes[$propertyKey], $defaultValue);
}
return $defaultValue;
}
/**
* Process the SAML response for a user. Login the user when
* they exist, optionally registering them automatically.
*
* @throws SamlException
* @throws JsonDebugException
* @throws UserRegistrationException
* @throws StoppedAuthenticationException
*/
public function processLoginCallback(string $samlID, array $samlAttributes): User
{
$userDetails = $this->getUserDetails($samlID, $samlAttributes);
$isLoggedIn = auth()->check();
if ($this->shouldSyncGroups()) {
$userDetails['groups'] = $this->getUserGroups($samlAttributes);
}
if ($this->config['dump_user_details']) {
throw new JsonDebugException([
'id_from_idp' => $samlID,
'attrs_from_idp' => $samlAttributes,
'attrs_after_parsing' => $userDetails,
]);
}
if ($userDetails['email'] === null) {
throw new SamlException(trans('errors.saml_no_email_address'));
}
if ($isLoggedIn) {
throw new SamlException(trans('errors.saml_already_logged_in'), '/login');
}
$user = $this->registrationService->findOrRegister(
$userDetails['name'],
$userDetails['email'],
$userDetails['external_id']
);
if ($this->shouldSyncGroups()) {
$this->groupSyncService->syncUserWithFoundGroups($user, $userDetails['groups'], $this->config['remove_from_groups']);
}
$this->loginService->login($user, 'saml2');
return $user;
}
}

View File

@@ -0,0 +1,36 @@
<?php
namespace BookStack\Access;
use BookStack\Activity\Models\Loggable;
use BookStack\App\Model;
use BookStack\Users\Models\User;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
/**
* @property string $driver
* @property User $user
*/
class SocialAccount extends Model implements Loggable
{
use HasFactory;
protected $fillable = ['user_id', 'driver', 'driver_id'];
/**
* @return BelongsTo<User, $this>
*/
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
/**
* {@inheritdoc}
*/
public function logDescriptor(): string
{
return "{$this->driver}; {$this->user->logDescriptor()}";
}
}

View File

@@ -0,0 +1,185 @@
<?php
namespace BookStack\Access;
use BookStack\Exceptions\SocialDriverNotConfigured;
use BookStack\Exceptions\SocialSignInAccountNotUsed;
use BookStack\Exceptions\UserRegistrationException;
use BookStack\Users\Models\User;
use Illuminate\Support\Str;
use Laravel\Socialite\Contracts\Factory as Socialite;
use Laravel\Socialite\Contracts\Provider;
use Laravel\Socialite\Contracts\User as SocialUser;
use Laravel\Socialite\Two\GoogleProvider;
use Symfony\Component\HttpFoundation\RedirectResponse;
class SocialAuthService
{
public function __construct(
protected Socialite $socialite,
protected LoginService $loginService,
protected SocialDriverManager $driverManager,
) {
}
/**
* Start the social login path.
*
* @throws SocialDriverNotConfigured
*/
public function startLogIn(string $socialDriver): RedirectResponse
{
$socialDriver = trim(strtolower($socialDriver));
$this->driverManager->ensureDriverActive($socialDriver);
return $this->getDriverForRedirect($socialDriver)->redirect();
}
/**
* Start the social registration process.
*
* @throws SocialDriverNotConfigured
*/
public function startRegister(string $socialDriver): RedirectResponse
{
$socialDriver = trim(strtolower($socialDriver));
$this->driverManager->ensureDriverActive($socialDriver);
return $this->getDriverForRedirect($socialDriver)->redirect();
}
/**
* Handle the social registration process on callback.
*
* @throws UserRegistrationException
*/
public function handleRegistrationCallback(string $socialDriver, SocialUser $socialUser): SocialUser
{
// Check social account has not already been used
if (SocialAccount::query()->where('driver_id', '=', $socialUser->getId())->exists()) {
throw new UserRegistrationException(trans('errors.social_account_in_use', ['socialAccount' => $socialDriver]), '/login');
}
if (User::query()->where('email', '=', $socialUser->getEmail())->exists()) {
$email = $socialUser->getEmail();
throw new UserRegistrationException(trans('errors.error_user_exists_different_creds', ['email' => $email]), '/login');
}
return $socialUser;
}
/**
* Get the social user details via the social driver.
*
* @throws SocialDriverNotConfigured
*/
public function getSocialUser(string $socialDriver): SocialUser
{
$socialDriver = trim(strtolower($socialDriver));
$this->driverManager->ensureDriverActive($socialDriver);
return $this->socialite->driver($socialDriver)->user();
}
/**
* Handle the login process on a oAuth callback.
*
* @throws SocialSignInAccountNotUsed
*/
public function handleLoginCallback(string $socialDriver, SocialUser $socialUser)
{
$socialDriver = trim(strtolower($socialDriver));
$socialId = $socialUser->getId();
// Get any attached social accounts or users
$socialAccount = SocialAccount::query()->where('driver_id', '=', $socialId)->first();
$isLoggedIn = auth()->check();
$currentUser = user();
$titleCaseDriver = Str::title($socialDriver);
// When a user is not logged in and a matching SocialAccount exists,
// Simply log the user into the application.
if (!$isLoggedIn && $socialAccount !== null) {
$this->loginService->login($socialAccount->user, $socialDriver);
return redirect()->intended('/');
}
// When a user is logged in but the social account does not exist,
// Create the social account and attach it to the user & redirect to the profile page.
if ($isLoggedIn && $socialAccount === null) {
$account = $this->newSocialAccount($socialDriver, $socialUser);
$currentUser->socialAccounts()->save($account);
session()->flash('success', trans('settings.users_social_connected', ['socialAccount' => $titleCaseDriver]));
return redirect('/my-account/auth#social_accounts');
}
// When a user is logged in and the social account exists and is already linked to the current user.
if ($isLoggedIn && $socialAccount !== null && $socialAccount->user->id === $currentUser->id) {
session()->flash('error', trans('errors.social_account_existing', ['socialAccount' => $titleCaseDriver]));
return redirect('/my-account/auth#social_accounts');
}
// When a user is logged in, A social account exists but the users do not match.
if ($isLoggedIn && $socialAccount !== null && $socialAccount->user->id != $currentUser->id) {
session()->flash('error', trans('errors.social_account_already_used_existing', ['socialAccount' => $titleCaseDriver]));
return redirect('/my-account/auth#social_accounts');
}
// Otherwise let the user know this social account is not used by anyone.
$message = trans('errors.social_account_not_used', ['socialAccount' => $titleCaseDriver]);
if (setting('registration-enabled') && config('auth.method') !== 'ldap' && config('auth.method') !== 'saml2') {
$message .= trans('errors.social_account_register_instructions', ['socialAccount' => $titleCaseDriver]);
}
throw new SocialSignInAccountNotUsed($message, '/login');
}
/**
* Get the social driver manager used by this service.
*/
public function drivers(): SocialDriverManager
{
return $this->driverManager;
}
/**
* Fill and return a SocialAccount from the given driver name and SocialUser.
*/
public function newSocialAccount(string $socialDriver, SocialUser $socialUser): SocialAccount
{
return new SocialAccount([
'driver' => $socialDriver,
'driver_id' => $socialUser->getId(),
'avatar' => $socialUser->getAvatar(),
]);
}
/**
* Detach a social account from a user.
*/
public function detachSocialAccount(string $socialDriver): void
{
user()->socialAccounts()->where('driver', '=', $socialDriver)->delete();
}
/**
* Provide redirect options per service for the Laravel Socialite driver.
*/
protected function getDriverForRedirect(string $driverName): Provider
{
$driver = $this->socialite->driver($driverName);
if ($driver instanceof GoogleProvider && config('services.google.select_account')) {
$driver->with(['prompt' => 'select_account']);
}
$this->driverManager->getConfigureForRedirectCallback($driverName)($driver);
return $driver;
}
}

View File

@@ -0,0 +1,147 @@
<?php
namespace BookStack\Access;
use BookStack\Exceptions\SocialDriverNotConfigured;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Str;
use SocialiteProviders\Manager\SocialiteWasCalled;
class SocialDriverManager
{
/**
* The default built-in social drivers we support.
*
* @var string[]
*/
protected array $validDrivers = [
'google',
'github',
'facebook',
'slack',
'twitter',
'azure',
'okta',
'gitlab',
'twitch',
'discord',
];
/**
* Callbacks to run when configuring a social driver
* for an initial redirect action.
* Array is keyed by social driver name.
* Callbacks are passed an instance of the driver.
*
* @var array<string, callable>
*/
protected array $configureForRedirectCallbacks = [];
/**
* Check if the current config for the given driver allows auto-registration.
*/
public function isAutoRegisterEnabled(string $driver): bool
{
return $this->getDriverConfigProperty($driver, 'auto_register') === true;
}
/**
* Check if the current config for the given driver allow email address auto-confirmation.
*/
public function isAutoConfirmEmailEnabled(string $driver): bool
{
return $this->getDriverConfigProperty($driver, 'auto_confirm') === true;
}
/**
* Gets the names of the active social drivers, keyed by driver id.
* @return array<string, string>
*/
public function getActive(): array
{
$activeDrivers = [];
foreach ($this->validDrivers as $driverKey) {
if ($this->checkDriverConfigured($driverKey)) {
$activeDrivers[$driverKey] = $this->getName($driverKey);
}
}
return $activeDrivers;
}
/**
* Get the configure-for-redirect callback for the given driver.
* This is a callable that allows modification of the driver at redirect time.
* Commonly used to perform custom dynamic configuration where required.
* The callback is passed a \Laravel\Socialite\Contracts\Provider instance.
*/
public function getConfigureForRedirectCallback(string $driver): callable
{
return $this->configureForRedirectCallbacks[$driver] ?? (fn() => true);
}
/**
* Add a custom socialite driver to be used.
* Driver name should be lower_snake_case.
* Config array should mirror the structure of a service
* within the `Config/services.php` file.
* Handler should be a Class@method handler to the SocialiteWasCalled event.
*/
public function addSocialDriver(
string $driverName,
array $config,
string $socialiteHandler,
?callable $configureForRedirect = null
) {
$this->validDrivers[] = $driverName;
config()->set('services.' . $driverName, $config);
config()->set('services.' . $driverName . '.redirect', url('/login/service/' . $driverName . '/callback'));
config()->set('services.' . $driverName . '.name', $config['name'] ?? $driverName);
Event::listen(SocialiteWasCalled::class, $socialiteHandler);
if (!is_null($configureForRedirect)) {
$this->configureForRedirectCallbacks[$driverName] = $configureForRedirect;
}
}
/**
* Get the presentational name for a driver.
*/
protected function getName(string $driver): string
{
return $this->getDriverConfigProperty($driver, 'name') ?? '';
}
protected function getDriverConfigProperty(string $driver, string $property): mixed
{
return config("services.{$driver}.{$property}");
}
/**
* Ensure the social driver is correct and supported.
*
* @throws SocialDriverNotConfigured
*/
public function ensureDriverActive(string $driverName): void
{
if (!in_array($driverName, $this->validDrivers)) {
abort(404, trans('errors.social_driver_not_found'));
}
if (!$this->checkDriverConfigured($driverName)) {
throw new SocialDriverNotConfigured(trans('errors.social_driver_not_configured', ['socialAccount' => Str::title($driverName)]));
}
}
/**
* Check a social driver has been configured correctly.
*/
protected function checkDriverConfigured(string $driver): bool
{
$lowerName = strtolower($driver);
$configPrefix = 'services.' . $lowerName . '.';
$config = [config($configPrefix . 'client_id'), config($configPrefix . 'client_secret'), config('services.callback_url')];
return !in_array(false, $config) && !in_array(null, $config);
}
}

View File

@@ -0,0 +1,10 @@
<?php
namespace BookStack\Access;
use Exception;
class UserInviteException extends Exception
{
//
}

View File

@@ -0,0 +1,29 @@
<?php
namespace BookStack\Access;
use BookStack\Access\Notifications\UserInviteNotification;
use BookStack\Users\Models\User;
class UserInviteService extends UserTokenService
{
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.
* @throws UserInviteException
*/
public function sendInvitation(User $user)
{
$this->deleteByUser($user);
$token = $this->createTokenForUser($user);
try {
$user->notify(new UserInviteNotification($token));
} catch (\Exception $exception) {
throw new UserInviteException($exception->getMessage(), $exception->getCode(), $exception);
}
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,17 +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

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

View File

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

View File

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

View File

@@ -0,0 +1,117 @@
<?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\Entities\Tools\MixedEntityListLoader;
use BookStack\Permissions\PermissionApplicator;
use BookStack\Users\Models\User;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Relations\MorphTo;
use Illuminate\Database\Eloquent\Relations\Relation;
class ActivityQueries
{
public function __construct(
protected PermissionApplicator $permissions,
protected MixedEntityListLoader $listLoader,
) {
}
/**
* Gets the latest activity.
*/
public function latest(int $count = 20, int $page = 0): array
{
$activityList = $this->permissions
->restrictEntityRelationQuery(Activity::query(), 'activities', 'loggable_id', 'loggable_type')
->orderBy('created_at', 'desc')
->with(['user'])
->skip($count * $page)
->take($count)
->get();
$this->listLoader->loadIntoRelations($activityList->all(), 'loggable', false);
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('loggable_type', '=', $morphClass)
->whereIn('loggable_id', $idArr);
});
}
});
$activity = $query->orderBy('created_at', 'desc')
->with(['loggable' => function (Relation $query) {
/** @var MorphTo<Entity, Activity> $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', 'loggable_id', 'loggable_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

@@ -0,0 +1,85 @@
<?php
namespace BookStack\Activity;
class ActivityType
{
const PAGE_CREATE = 'page_create';
const PAGE_UPDATE = 'page_update';
const PAGE_DELETE = 'page_delete';
const PAGE_RESTORE = 'page_restore';
const PAGE_MOVE = 'page_move';
const CHAPTER_CREATE = 'chapter_create';
const CHAPTER_UPDATE = 'chapter_update';
const CHAPTER_DELETE = 'chapter_delete';
const CHAPTER_MOVE = 'chapter_move';
const BOOK_CREATE = 'book_create';
const BOOK_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';
const RECYCLE_BIN_EMPTY = 'recycle_bin_empty';
const RECYCLE_BIN_RESTORE = 'recycle_bin_restore';
const RECYCLE_BIN_DESTROY = 'recycle_bin_destroy';
const USER_CREATE = 'user_create';
const USER_UPDATE = 'user_update';
const USER_DELETE = 'user_delete';
const API_TOKEN_CREATE = 'api_token_create';
const API_TOKEN_UPDATE = 'api_token_update';
const API_TOKEN_DELETE = 'api_token_delete';
const ROLE_CREATE = 'role_create';
const ROLE_UPDATE = 'role_update';
const ROLE_DELETE = 'role_delete';
const AUTH_PASSWORD_RESET = 'auth_password_reset_request';
const AUTH_PASSWORD_RESET_UPDATE = 'auth_password_reset_update';
const AUTH_LOGIN = 'auth_login';
const AUTH_REGISTER = 'auth_register';
const MFA_SETUP_METHOD = 'mfa_setup_method';
const MFA_REMOVE_METHOD = 'mfa_remove_method';
const WEBHOOK_CREATE = 'webhook_create';
const WEBHOOK_UPDATE = 'webhook_update';
const WEBHOOK_DELETE = 'webhook_delete';
const IMPORT_CREATE = 'import_create';
const IMPORT_RUN = 'import_run';
const IMPORT_DELETE = 'import_delete';
const SORT_RULE_CREATE = 'sort_rule_create';
const SORT_RULE_UPDATE = 'sort_rule_update';
const SORT_RULE_DELETE = 'sort_rule_delete';
/**
* Get all the possible values.
*/
public static function all(): array
{
return (new \ReflectionClass(static::class))->getConstants();
}
}

View File

@@ -0,0 +1,153 @@
<?php
namespace BookStack\Activity;
use BookStack\Activity\Models\Comment;
use BookStack\Entities\Models\Entity;
use BookStack\Entities\Models\Page;
use BookStack\Exceptions\NotifyException;
use BookStack\Facades\Activity as ActivityService;
use BookStack\Util\HtmlDescriptionFilter;
use Illuminate\Database\Eloquent\Builder;
class CommentRepo
{
/**
* Get a comment by ID.
*/
public function getById(int $id): Comment
{
return Comment::query()->findOrFail($id);
}
/**
* Get a comment by ID, ensuring it is visible to the user based upon access to the page
* which the comment is attached to.
*/
public function getVisibleById(int $id): Comment
{
return $this->getQueryForVisible()->findOrFail($id);
}
/**
* Start a query for comments visible to the user.
* @return Builder<Comment>
*/
public function getQueryForVisible(): Builder
{
return Comment::query()->scopes('visible');
}
/**
* Create a new comment on an entity.
*/
public function create(Entity $entity, string $html, ?int $parentId, string $contentRef): Comment
{
// Prevent comments being added to draft pages
if ($entity instanceof Page && $entity->draft) {
throw new \Exception(trans('errors.cannot_add_comment_to_draft'));
}
// Validate parent ID
if ($parentId !== null) {
$parentCommentExists = Comment::query()
->where('commentable_id', '=', $entity->id)
->where('commentable_type', '=', $entity->getMorphClass())
->where('local_id', '=', $parentId)
->exists();
if (!$parentCommentExists) {
$parentId = null;
}
}
$userId = user()->id;
$comment = new Comment();
$comment->html = HtmlDescriptionFilter::filterFromString($html);
$comment->created_by = $userId;
$comment->updated_by = $userId;
$comment->local_id = $this->getNextLocalId($entity);
$comment->parent_id = $parentId;
$comment->content_ref = preg_match('/^bkmrk-(.*?):\d+:(\d*-\d*)?$/', $contentRef) === 1 ? $contentRef : '';
$entity->comments()->save($comment);
ActivityService::add(ActivityType::COMMENT_CREATE, $comment);
ActivityService::add(ActivityType::COMMENTED_ON, $entity);
$comment->refresh()->unsetRelations();
return $comment;
}
/**
* Update an existing comment.
*/
public function update(Comment $comment, string $html): Comment
{
$comment->updated_by = user()->id;
$comment->html = HtmlDescriptionFilter::filterFromString($html);
$comment->save();
ActivityService::add(ActivityType::COMMENT_UPDATE, $comment);
return $comment;
}
/**
* Archive an existing comment.
*/
public function archive(Comment $comment, bool $log = true): Comment
{
if ($comment->parent_id) {
throw new NotifyException('Only top-level comments can be archived.', '/', 400);
}
$comment->archived = true;
$comment->save();
if ($log) {
ActivityService::add(ActivityType::COMMENT_UPDATE, $comment);
}
return $comment;
}
/**
* Un-archive an existing comment.
*/
public function unarchive(Comment $comment, bool $log = true): Comment
{
if ($comment->parent_id) {
throw new NotifyException('Only top-level comments can be un-archived.', '/', 400);
}
$comment->archived = false;
$comment->save();
if ($log) {
ActivityService::add(ActivityType::COMMENT_UPDATE, $comment);
}
return $comment;
}
/**
* Delete a comment from the system.
*/
public function delete(Comment $comment): void
{
$comment->delete();
ActivityService::add(ActivityType::COMMENT_DELETE, $comment);
}
/**
* Get the next local ID relative to the linked entity.
*/
protected function getNextLocalId(Entity $entity): int
{
$currentMaxId = $entity->comments()->max('local_id');
return $currentMaxId + 1;
}
}

View File

@@ -0,0 +1,29 @@
<?php
namespace BookStack\Activity\Controllers;
use BookStack\Activity\Models\Activity;
use BookStack\Http\ApiController;
use BookStack\Permissions\Permission;
class AuditLogApiController extends ApiController
{
/**
* Get a listing of audit log events in the system.
* The loggable relation fields currently only relates to core
* content types (page, book, bookshelf, chapter) but this may be
* used more in the future across other types.
* Requires permission to manage both users and system settings.
*/
public function list()
{
$this->checkPermission(Permission::SettingsManage);
$this->checkPermission(Permission::UsersManage);
$query = Activity::query()->with(['user']);
return $this->apiListingResponse($query, [
'id', 'type', 'detail', 'user_id', 'loggable_id', 'loggable_type', 'ip', 'created_at',
]);
}
}

View File

@@ -0,0 +1,73 @@
<?php
namespace BookStack\Activity\Controllers;
use BookStack\Activity\ActivityType;
use BookStack\Activity\Models\Activity;
use BookStack\Http\Controller;
use BookStack\Permissions\Permission;
use BookStack\Sorting\SortUrl;
use BookStack\Util\SimpleListOptions;
use Illuminate\Http\Request;
class AuditLogController extends Controller
{
public function index(Request $request)
{
$this->checkPermission(Permission::SettingsManage);
$this->checkPermission(Permission::UsersManage);
$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([
'loggable' => 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,
'filterSortUrl' => new SortUrl('settings/audit', array_filter($request->except('page')))
]);
}
}

View File

@@ -0,0 +1,148 @@
<?php
declare(strict_types=1);
namespace BookStack\Activity\Controllers;
use BookStack\Activity\CommentRepo;
use BookStack\Activity\Models\Comment;
use BookStack\Entities\Queries\PageQueries;
use BookStack\Http\ApiController;
use BookStack\Permissions\Permission;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
/**
* The comment data model has a 'local_id' property, which is a unique integer ID
* scoped to the page which the comment is on. The 'parent_id' is used for replies
* and refers to the 'local_id' of the parent comment on the same page, not the main
* globally unique 'id'.
*
* If you want to get all comments for a page in a tree-like structure, as reflected in
* the UI, then that is provided on pages-read API responses.
*/
class CommentApiController extends ApiController
{
protected array $rules = [
'create' => [
'page_id' => ['required', 'integer'],
'reply_to' => ['nullable', 'integer'],
'html' => ['required', 'string'],
'content_ref' => ['string'],
],
'update' => [
'html' => ['string'],
'archived' => ['boolean'],
]
];
public function __construct(
protected CommentRepo $commentRepo,
protected PageQueries $pageQueries,
) {
}
/**
* Get a listing of comments visible to the user.
*/
public function list(): JsonResponse
{
$query = $this->commentRepo->getQueryForVisible();
return $this->apiListingResponse($query, [
'id', 'commentable_id', 'commentable_type', 'parent_id', 'local_id', 'content_ref', 'created_by', 'updated_by', 'created_at', 'updated_at'
]);
}
/**
* Create a new comment on a page.
* If commenting as a reply to an existing comment, the 'reply_to' parameter
* should be provided, set to the 'local_id' of the comment being replied to.
*/
public function create(Request $request): JsonResponse
{
$this->checkPermission(Permission::CommentCreateAll);
$input = $this->validate($request, $this->rules()['create']);
$page = $this->pageQueries->findVisibleByIdOrFail($input['page_id']);
$comment = $this->commentRepo->create(
$page,
$input['html'],
$input['reply_to'] ?? null,
$input['content_ref'] ?? '',
);
return response()->json($comment);
}
/**
* Read the details of a single comment, along with its direct replies.
*/
public function read(string $id): JsonResponse
{
$comment = $this->commentRepo->getVisibleById(intval($id));
$comment->load('createdBy', 'updatedBy');
$replies = $this->commentRepo->getQueryForVisible()
->where('parent_id', '=', $comment->local_id)
->where('commentable_id', '=', $comment->commentable_id)
->where('commentable_type', '=', $comment->commentable_type)
->get();
/** @var Comment[] $toProcess */
$toProcess = [$comment, ...$replies];
foreach ($toProcess as $commentToProcess) {
$commentToProcess->setAttribute('html', $commentToProcess->safeHtml());
$commentToProcess->makeVisible('html');
}
$comment->setRelation('replies', $replies);
return response()->json($comment);
}
/**
* Update the content or archived status of an existing comment.
*
* Only provide a new archived status if needing to actively change the archive state.
* Only top-level comments (non-replies) can be archived or unarchived.
*/
public function update(Request $request, string $id): JsonResponse
{
$comment = $this->commentRepo->getVisibleById(intval($id));
$this->checkOwnablePermission(Permission::CommentUpdate, $comment);
$input = $this->validate($request, $this->rules()['update']);
$hasHtml = isset($input['html']);
if (isset($input['archived'])) {
if ($input['archived']) {
$this->commentRepo->archive($comment, !$hasHtml);
} else {
$this->commentRepo->unarchive($comment, !$hasHtml);
}
}
if ($hasHtml) {
$comment = $this->commentRepo->update($comment, $input['html']);
}
return response()->json($comment);
}
/**
* Delete a single comment from the system.
*/
public function delete(string $id): Response
{
$comment = $this->commentRepo->getVisibleById(intval($id));
$this->checkOwnablePermission(Permission::CommentDelete, $comment);
$this->commentRepo->delete($comment);
return response('', 204);
}
}

View File

@@ -0,0 +1,126 @@
<?php
namespace BookStack\Activity\Controllers;
use BookStack\Activity\CommentRepo;
use BookStack\Activity\Tools\CommentTree;
use BookStack\Activity\Tools\CommentTreeNode;
use BookStack\Entities\Queries\PageQueries;
use BookStack\Http\Controller;
use BookStack\Permissions\Permission;
use Illuminate\Http\Request;
use Illuminate\Validation\ValidationException;
class CommentController extends Controller
{
public function __construct(
protected CommentRepo $commentRepo,
protected PageQueries $pageQueries,
) {
}
/**
* Save a new comment for a Page.
*
* @throws ValidationException|\Exception
*/
public function savePageComment(Request $request, int $pageId)
{
$input = $this->validate($request, [
'html' => ['required', 'string'],
'parent_id' => ['nullable', 'integer'],
'content_ref' => ['string'],
]);
$page = $this->pageQueries->findVisibleById($pageId);
if ($page === null) {
return response('Not found', 404);
}
// Create a new comment.
$this->checkPermission(Permission::CommentCreateAll);
$contentRef = $input['content_ref'] ?? '';
$comment = $this->commentRepo->create($page, $input['html'], $input['parent_id'] ?? null, $contentRef);
return view('comments.comment-branch', [
'readOnly' => false,
'branch' => new CommentTreeNode($comment, 0, []),
]);
}
/**
* Update an existing comment.
*
* @throws ValidationException
*/
public function update(Request $request, int $commentId)
{
$input = $this->validate($request, [
'html' => ['required', 'string'],
]);
$comment = $this->commentRepo->getById($commentId);
$this->checkOwnablePermission(Permission::PageView, $comment->entity);
$this->checkOwnablePermission(Permission::CommentUpdate, $comment);
$comment = $this->commentRepo->update($comment, $input['html']);
return view('comments.comment', [
'comment' => $comment,
'readOnly' => false,
]);
}
/**
* Mark a comment as archived.
*/
public function archive(int $id)
{
$comment = $this->commentRepo->getById($id);
$this->checkOwnablePermission(Permission::PageView, $comment->entity);
if (!userCan(Permission::CommentUpdate, $comment) && !userCan(Permission::CommentDelete, $comment)) {
$this->showPermissionError();
}
$this->commentRepo->archive($comment);
$tree = new CommentTree($comment->entity);
return view('comments.comment-branch', [
'readOnly' => false,
'branch' => $tree->getCommentNodeForId($id),
]);
}
/**
* Unmark a comment as archived.
*/
public function unarchive(int $id)
{
$comment = $this->commentRepo->getById($id);
$this->checkOwnablePermission(Permission::PageView, $comment->entity);
if (!userCan(Permission::CommentUpdate, $comment) && !userCan(Permission::CommentDelete, $comment)) {
$this->showPermissionError();
}
$this->commentRepo->unarchive($comment);
$tree = new CommentTree($comment->entity);
return view('comments.comment-branch', [
'readOnly' => false,
'branch' => $tree->getCommentNodeForId($id),
]);
}
/**
* Delete a comment from the system.
*/
public function destroy(int $id)
{
$comment = $this->commentRepo->getById($id);
$this->checkOwnablePermission(Permission::CommentDelete, $comment);
$this->commentRepo->delete($comment);
return response()->json(['message' => trans('entities.comment_deleted')]);
}
}

View File

@@ -0,0 +1,72 @@
<?php
namespace BookStack\Activity\Controllers;
use BookStack\Entities\Queries\QueryTopFavourites;
use BookStack\Entities\Tools\MixedEntityRequestHelper;
use BookStack\Http\Controller;
use Illuminate\Http\Request;
class FavouriteController extends Controller
{
public function __construct(
protected MixedEntityRequestHelper $entityHelper,
) {
}
/**
* Show a listing of all favourite items for the current user.
*/
public function index(Request $request, QueryTopFavourites $topFavourites)
{
$viewCount = 20;
$page = intval($request->get('page', 1));
$favourites = $topFavourites->run($viewCount + 1, (($page - 1) * $viewCount));
$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),
'hasMoreLink' => $hasMoreLink,
]);
}
/**
* Add a new item as a favourite.
*/
public function add(Request $request)
{
$modelInfo = $this->validate($request, $this->entityHelper->validationRules());
$entity = $this->entityHelper->getVisibleEntityFromRequestData($modelInfo);
$entity->favourites()->firstOrCreate([
'user_id' => user()->id,
]);
$this->showSuccessNotification(trans('activities.favourite_add_notification', [
'name' => $entity->name,
]));
return redirect($entity->getUrl());
}
/**
* Remove an item as a favourite.
*/
public function remove(Request $request)
{
$modelInfo = $this->validate($request, $this->entityHelper->validationRules());
$entity = $this->entityHelper->getVisibleEntityFromRequestData($modelInfo);
$entity->favourites()->where([
'user_id' => user()->id,
])->delete();
$this->showSuccessNotification(trans('activities.favourite_remove_notification', [
'name' => $entity->name,
]));
return redirect($entity->getUrl());
}
}

View File

@@ -0,0 +1,66 @@
<?php
namespace BookStack\Activity\Controllers;
use BookStack\Activity\TagRepo;
use BookStack\Http\Controller;
use BookStack\Util\SimpleListOptions;
use Illuminate\Http\Request;
class TagController extends Controller
{
public function __construct(
protected TagRepo $tagRepo
) {
}
/**
* Show a listing of existing tags in the system.
*/
public function index(Request $request)
{
$listOptions = SimpleListOptions::fromRequest($request, 'tags')->withSortOptions([
'name' => trans('common.sort_name'),
'usages' => trans('entities.tags_usages'),
]);
$nameFilter = $request->get('name', '');
$tags = $this->tagRepo
->queryWithTotals($listOptions, $nameFilter)
->paginate(50)
->appends(array_filter(array_merge($listOptions->getPaginationAppends(), [
'name' => $nameFilter,
])));
$this->setPageTitle(trans('entities.tags'));
return view('tags.index', [
'tags' => $tags,
'nameFilter' => $nameFilter,
'listOptions' => $listOptions,
]);
}
/**
* Get tag name suggestions from a given search term.
*/
public function getNameSuggestions(Request $request)
{
$searchTerm = $request->get('search', '');
$suggestions = $this->tagRepo->getNameSuggestions($searchTerm);
return response()->json($suggestions);
}
/**
* Get tag value suggestions from a given search term.
*/
public function getValueSuggestions(Request $request)
{
$searchTerm = $request->get('search', '');
$tagName = $request->get('name', '');
$suggestions = $this->tagRepo->getValueSuggestions($searchTerm, $tagName);
return response()->json($suggestions);
}
}

View File

@@ -0,0 +1,30 @@
<?php
namespace BookStack\Activity\Controllers;
use BookStack\Activity\Tools\UserEntityWatchOptions;
use BookStack\Entities\Tools\MixedEntityRequestHelper;
use BookStack\Http\Controller;
use BookStack\Permissions\Permission;
use Illuminate\Http\Request;
class WatchController extends Controller
{
public function update(Request $request, MixedEntityRequestHelper $entityHelper)
{
$this->checkPermission(Permission::ReceiveNotifications);
$this->preventGuestAccess();
$requestData = $this->validate($request, array_merge([
'level' => ['required', 'string'],
], $entityHelper->validationRules()));
$watchable = $entityHelper->getVisibleEntityFromRequestData($requestData);
$watchOptions = new UserEntityWatchOptions(user(), $watchable);
$watchOptions->updateLevelByName($requestData['level']);
$this->showSuccessNotification(trans('activities.watch_update_level_notification'));
return redirect($watchable->getUrl());
}
}

View File

@@ -0,0 +1,147 @@
<?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\Permissions\Permission;
use BookStack\Util\SimpleListOptions;
use Illuminate\Http\Request;
class WebhookController extends Controller
{
public function __construct()
{
$this->middleware([
Permission::SettingsManage->middleware()
]);
}
/**
* 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,84 @@
<?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\Http\HttpRequestService;
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\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(HttpRequestService $http)
{
$lastError = null;
try {
(new SsrUrlValidator())->ensureAllowed($this->webhook->endpoint);
$client = $http->buildClient($this->webhook->timeout, [
'connect_timeout' => 10,
'allow_redirects' => ['strict' => true],
]);
$response = $client->sendRequest($http->jsonRequest('POST', $this->webhook->endpoint, $this->webhookData));
$statusCode = $response->getStatusCode();
if ($statusCode >= 400) {
$lastError = "Response status from endpoint was {$statusCode}";
Log::error("Webhook call to endpoint {$this->webhook->endpoint} failed with status {$statusCode}");
}
} catch (\Exception $error) {
$lastError = $error->getMessage();
Log::error("Webhook call to endpoint {$this->webhook->endpoint} failed with error \"{$lastError}\"");
}
$this->webhook->last_called_at = now();
if ($lastError) {
$this->webhook->last_errored_at = now();
$this->webhook->last_error = $lastError;
}
$this->webhook->save();
}
}

View File

@@ -0,0 +1,80 @@
<?php
namespace BookStack\Activity\Models;
use BookStack\App\Model;
use BookStack\Entities\Models\Entity;
use BookStack\Permissions\Models\JointPermission;
use BookStack\Users\Models\User;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\MorphTo;
use Illuminate\Support\Carbon;
use Illuminate\Support\Str;
/**
* @property string $type
* @property User $user
* @property Entity $loggable
* @property string $detail
* @property string $loggable_type
* @property int $loggable_id
* @property int $user_id
* @property Carbon $created_at
*/
class Activity extends Model
{
use HasFactory;
/**
* Get the loggable model related to this activity.
* Currently only used for entities (previously entity_[id/type] columns).
* Could be used for others but will need an audit of uses where assumed
* to be entities.
*/
public function loggable(): MorphTo
{
return $this->morphTo('loggable');
}
/**
* Get the user this activity relates to.
*/
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
public function jointPermissions(): HasMany
{
return $this->hasMany(JointPermission::class, 'entity_id', 'loggable_id')
->whereColumn('activities.loggable_type', '=', 'joint_permissions.entity_type');
}
/**
* Returns text from the language files, Looks up by using the activity key.
*/
public function getText(): string
{
return trans('activities.' . $this->type);
}
/**
* Check if this activity is intended to be for an entity.
*/
public function isForEntity(): bool
{
return Str::startsWith($this->type, [
'page_', 'chapter_', 'book_', 'bookshelf_',
]);
}
/**
* Checks if another Activity matches the general information of another.
*/
public function isSimilarTo(self $activityB): bool
{
return [$this->type, $this->loggable_type, $this->loggable_id] === [$activityB->type, $activityB->loggable_type, $activityB->loggable_id];
}
}

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