Merge branch 'development' into release

This commit is contained in:
Dan Brown
2023-06-30 11:05:57 +01:00
687 changed files with 6947 additions and 3664 deletions

View File

@ -37,8 +37,10 @@ MAIL_FROM=bookstack@example.com
# SMTP mail options # SMTP mail options
# These settings can be checked using the "Send a Test Email" # These settings can be checked using the "Send a Test Email"
# feature found in the "Settings > Maintenance" area of the system. # 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_HOST=localhost
MAIL_PORT=1025 MAIL_PORT=587
MAIL_USERNAME=null MAIL_USERNAME=null
MAIL_PASSWORD=null MAIL_PASSWORD=null
MAIL_ENCRYPTION=null MAIL_ENCRYPTION=null

View File

@ -69,23 +69,19 @@ DB_PASSWORD=database_user_password
# certificate itself (Common Name or Subject Alternative Name). # certificate itself (Common Name or Subject Alternative Name).
MYSQL_ATTR_SSL_CA="/path/to/ca.pem" MYSQL_ATTR_SSL_CA="/path/to/ca.pem"
# Mail system to use # Mail configuration
# Can be 'smtp' or 'sendmail' # Refer to https://www.bookstackapp.com/docs/admin/email-webhooks/#email-configuration
MAIL_DRIVER=smtp MAIL_DRIVER=smtp
# Mail sending options
MAIL_FROM=mail@bookstackapp.com MAIL_FROM=mail@bookstackapp.com
MAIL_FROM_NAME=BookStack MAIL_FROM_NAME=BookStack
# SMTP mail options
MAIL_HOST=localhost MAIL_HOST=localhost
MAIL_PORT=1025 MAIL_PORT=587
MAIL_USERNAME=null MAIL_USERNAME=null
MAIL_PASSWORD=null MAIL_PASSWORD=null
MAIL_ENCRYPTION=null MAIL_ENCRYPTION=null
MAIL_VERIFY_SSL=true MAIL_VERIFY_SSL=true
# Command to use when email is sent via sendmail
MAIL_SENDMAIL_COMMAND="/usr/sbin/sendmail -bs" MAIL_SENDMAIL_COMMAND="/usr/sbin/sendmail -bs"
# Cache & Session driver to use # Cache & Session driver to use

View File

@ -333,3 +333,11 @@ Patrick Dantas (pa-tiq) :: Portuguese, Brazilian
Michal (michalgurcik) :: Slovak Michal (michalgurcik) :: Slovak
Nepomacs :: German Nepomacs :: German
Rubens (rubenix) :: Catalan 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

View File

@ -1,14 +1,14 @@
<?php <?php
namespace BookStack\Http\Controllers\Auth; namespace BookStack\Access\Controllers;
use BookStack\Auth\Access\EmailConfirmationService; use BookStack\Access\EmailConfirmationService;
use BookStack\Auth\Access\LoginService; use BookStack\Access\LoginService;
use BookStack\Auth\UserRepo;
use BookStack\Exceptions\ConfirmationEmailException; use BookStack\Exceptions\ConfirmationEmailException;
use BookStack\Exceptions\UserTokenExpiredException; use BookStack\Exceptions\UserTokenExpiredException;
use BookStack\Exceptions\UserTokenNotFoundException; use BookStack\Exceptions\UserTokenNotFoundException;
use BookStack\Http\Controllers\Controller; use BookStack\Http\Controller;
use BookStack\Users\UserRepo;
use Exception; use Exception;
use Illuminate\Http\Request; use Illuminate\Http\Request;

View File

@ -1,9 +1,9 @@
<?php <?php
namespace BookStack\Http\Controllers\Auth; namespace BookStack\Access\Controllers;
use BookStack\Actions\ActivityType; use BookStack\Activity\ActivityType;
use BookStack\Http\Controllers\Controller; use BookStack\Http\Controller;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Password; use Illuminate\Support\Facades\Password;

View File

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

View File

@ -1,13 +1,13 @@
<?php <?php
namespace BookStack\Http\Controllers\Auth; namespace BookStack\Access\Controllers;
use BookStack\Auth\Access\LoginService; use BookStack\Access\LoginService;
use BookStack\Auth\Access\SocialAuthService; use BookStack\Access\SocialAuthService;
use BookStack\Exceptions\LoginAttemptEmailNeededException; use BookStack\Exceptions\LoginAttemptEmailNeededException;
use BookStack\Exceptions\LoginAttemptException; use BookStack\Exceptions\LoginAttemptException;
use BookStack\Facades\Activity; use BookStack\Facades\Activity;
use BookStack\Http\Controllers\Controller; use BookStack\Http\Controller;
use Illuminate\Http\RedirectResponse; use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Auth;

View File

@ -1,14 +1,14 @@
<?php <?php
namespace BookStack\Http\Controllers\Auth; namespace BookStack\Access\Controllers;
use BookStack\Actions\ActivityType; use BookStack\Access\LoginService;
use BookStack\Auth\Access\LoginService; use BookStack\Access\Mfa\BackupCodeService;
use BookStack\Auth\Access\Mfa\BackupCodeService; use BookStack\Access\Mfa\MfaSession;
use BookStack\Auth\Access\Mfa\MfaSession; use BookStack\Access\Mfa\MfaValue;
use BookStack\Auth\Access\Mfa\MfaValue; use BookStack\Activity\ActivityType;
use BookStack\Exceptions\NotFoundException; use BookStack\Exceptions\NotFoundException;
use BookStack\Http\Controllers\Controller; use BookStack\Http\Controller;
use Exception; use Exception;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Validation\ValidationException; use Illuminate\Validation\ValidationException;

View File

@ -1,10 +1,10 @@
<?php <?php
namespace BookStack\Http\Controllers\Auth; namespace BookStack\Access\Controllers;
use BookStack\Actions\ActivityType; use BookStack\Access\Mfa\MfaValue;
use BookStack\Auth\Access\Mfa\MfaValue; use BookStack\Activity\ActivityType;
use BookStack\Http\Controllers\Controller; use BookStack\Http\Controller;
use Illuminate\Http\Request; use Illuminate\Http\Request;
class MfaController extends Controller class MfaController extends Controller

View File

@ -1,15 +1,15 @@
<?php <?php
namespace BookStack\Http\Controllers\Auth; namespace BookStack\Access\Controllers;
use BookStack\Actions\ActivityType; use BookStack\Access\LoginService;
use BookStack\Auth\Access\LoginService; use BookStack\Access\Mfa\MfaSession;
use BookStack\Auth\Access\Mfa\MfaSession; use BookStack\Access\Mfa\MfaValue;
use BookStack\Auth\Access\Mfa\MfaValue; use BookStack\Access\Mfa\TotpService;
use BookStack\Auth\Access\Mfa\TotpService; use BookStack\Access\Mfa\TotpValidationRule;
use BookStack\Auth\Access\Mfa\TotpValidationRule; use BookStack\Activity\ActivityType;
use BookStack\Exceptions\NotFoundException; use BookStack\Exceptions\NotFoundException;
use BookStack\Http\Controllers\Controller; use BookStack\Http\Controller;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Validation\ValidationException; use Illuminate\Validation\ValidationException;

View File

@ -1,10 +1,10 @@
<?php <?php
namespace BookStack\Http\Controllers\Auth; namespace BookStack\Access\Controllers;
use BookStack\Auth\Access\Oidc\OidcException; use BookStack\Access\Oidc\OidcException;
use BookStack\Auth\Access\Oidc\OidcService; use BookStack\Access\Oidc\OidcService;
use BookStack\Http\Controllers\Controller; use BookStack\Http\Controller;
use Illuminate\Http\Request; use Illuminate\Http\Request;
class OidcController extends Controller class OidcController extends Controller

View File

@ -1,13 +1,13 @@
<?php <?php
namespace BookStack\Http\Controllers\Auth; namespace BookStack\Access\Controllers;
use BookStack\Auth\Access\LoginService; use BookStack\Access\LoginService;
use BookStack\Auth\Access\RegistrationService; use BookStack\Access\RegistrationService;
use BookStack\Auth\Access\SocialAuthService; use BookStack\Access\SocialAuthService;
use BookStack\Exceptions\StoppedAuthenticationException; use BookStack\Exceptions\StoppedAuthenticationException;
use BookStack\Exceptions\UserRegistrationException; use BookStack\Exceptions\UserRegistrationException;
use BookStack\Http\Controllers\Controller; use BookStack\Http\Controller;
use Illuminate\Contracts\Validation\Validator as ValidatorContract; use Illuminate\Contracts\Validation\Validator as ValidatorContract;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator; use Illuminate\Support\Facades\Validator;

View File

@ -1,11 +1,11 @@
<?php <?php
namespace BookStack\Http\Controllers\Auth; namespace BookStack\Access\Controllers;
use BookStack\Actions\ActivityType; use BookStack\Access\LoginService;
use BookStack\Auth\Access\LoginService; use BookStack\Activity\ActivityType;
use BookStack\Auth\User; use BookStack\Http\Controller;
use BookStack\Http\Controllers\Controller; use BookStack\Users\Models\User;
use Illuminate\Http\RedirectResponse; use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Hash;

View File

@ -1,9 +1,9 @@
<?php <?php
namespace BookStack\Http\Controllers\Auth; namespace BookStack\Access\Controllers;
use BookStack\Auth\Access\Saml2Service; use BookStack\Access\Saml2Service;
use BookStack\Http\Controllers\Controller; use BookStack\Http\Controller;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Str; use Illuminate\Support\Str;

View File

@ -1,15 +1,15 @@
<?php <?php
namespace BookStack\Http\Controllers\Auth; namespace BookStack\Access\Controllers;
use BookStack\Auth\Access\LoginService; use BookStack\Access\LoginService;
use BookStack\Auth\Access\RegistrationService; use BookStack\Access\RegistrationService;
use BookStack\Auth\Access\SocialAuthService; use BookStack\Access\SocialAuthService;
use BookStack\Exceptions\SocialDriverNotConfigured; use BookStack\Exceptions\SocialDriverNotConfigured;
use BookStack\Exceptions\SocialSignInAccountNotUsed; use BookStack\Exceptions\SocialSignInAccountNotUsed;
use BookStack\Exceptions\SocialSignInException; use BookStack\Exceptions\SocialSignInException;
use BookStack\Exceptions\UserRegistrationException; use BookStack\Exceptions\UserRegistrationException;
use BookStack\Http\Controllers\Controller; use BookStack\Http\Controller;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Str; use Illuminate\Support\Str;
use Laravel\Socialite\Contracts\User as SocialUser; use Laravel\Socialite\Contracts\User as SocialUser;

View File

@ -1,6 +1,6 @@
<?php <?php
namespace BookStack\Http\Controllers\Auth; namespace BookStack\Access\Controllers;
use Illuminate\Cache\RateLimiter; use Illuminate\Cache\RateLimiter;
use Illuminate\Http\Request; use Illuminate\Http\Request;

View File

@ -1,12 +1,12 @@
<?php <?php
namespace BookStack\Http\Controllers\Auth; namespace BookStack\Access\Controllers;
use BookStack\Auth\Access\UserInviteService; use BookStack\Access\UserInviteService;
use BookStack\Auth\UserRepo;
use BookStack\Exceptions\UserTokenExpiredException; use BookStack\Exceptions\UserTokenExpiredException;
use BookStack\Exceptions\UserTokenNotFoundException; use BookStack\Exceptions\UserTokenNotFoundException;
use BookStack\Http\Controllers\Controller; use BookStack\Http\Controller;
use BookStack\Users\UserRepo;
use Exception; use Exception;
use Illuminate\Http\RedirectResponse; use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request; use Illuminate\Http\Request;

View File

@ -1,10 +1,10 @@
<?php <?php
namespace BookStack\Auth\Access; namespace BookStack\Access;
use BookStack\Auth\User;
use BookStack\Exceptions\ConfirmationEmailException; use BookStack\Exceptions\ConfirmationEmailException;
use BookStack\Notifications\ConfirmEmail; use BookStack\Notifications\ConfirmEmail;
use BookStack\Users\Models\User;
class EmailConfirmationService extends UserTokenService class EmailConfirmationService extends UserTokenService
{ {

View File

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

View File

@ -1,9 +1,9 @@
<?php <?php
namespace BookStack\Auth\Access; namespace BookStack\Access;
use BookStack\Auth\Role; use BookStack\Users\Models\Role;
use BookStack\Auth\User; use BookStack\Users\Models\User;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
class GroupSyncService class GroupSyncService

View File

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

View File

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

View File

@ -1,15 +1,15 @@
<?php <?php
namespace BookStack\Auth\Access\Guards; namespace BookStack\Access\Guards;
use BookStack\Auth\Access\LdapService; use BookStack\Access\LdapService;
use BookStack\Auth\Access\RegistrationService; use BookStack\Access\RegistrationService;
use BookStack\Auth\User;
use BookStack\Exceptions\JsonDebugException; use BookStack\Exceptions\JsonDebugException;
use BookStack\Exceptions\LdapException; use BookStack\Exceptions\LdapException;
use BookStack\Exceptions\LoginAttemptEmailNeededException; use BookStack\Exceptions\LoginAttemptEmailNeededException;
use BookStack\Exceptions\LoginAttemptException; use BookStack\Exceptions\LoginAttemptException;
use BookStack\Exceptions\UserRegistrationException; use BookStack\Exceptions\UserRegistrationException;
use BookStack\Users\Models\User;
use Illuminate\Contracts\Auth\UserProvider; use Illuminate\Contracts\Auth\UserProvider;
use Illuminate\Contracts\Session\Session; use Illuminate\Contracts\Session\Session;
use Illuminate\Support\Str; use Illuminate\Support\Str;

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

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

View File

@ -1,11 +1,11 @@
<?php <?php
namespace BookStack\Auth\Access; namespace BookStack\Access;
use BookStack\Auth\User;
use BookStack\Exceptions\JsonDebugException; use BookStack\Exceptions\JsonDebugException;
use BookStack\Exceptions\LdapException; use BookStack\Exceptions\LdapException;
use BookStack\Uploads\UserAvatars; use BookStack\Uploads\UserAvatars;
use BookStack\Users\Models\User;
use ErrorException; use ErrorException;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
@ -15,26 +15,19 @@ use Illuminate\Support\Facades\Log;
*/ */
class LdapService class LdapService
{ {
protected Ldap $ldap;
protected GroupSyncService $groupSyncService;
protected UserAvatars $userAvatars;
/** /**
* @var resource * @var resource|\LDAP\Connection
*/ */
protected $ldapConnection; protected $ldapConnection;
protected array $config; protected array $config;
protected bool $enabled; protected bool $enabled;
/** public function __construct(
* LdapService constructor. protected Ldap $ldap,
*/ protected UserAvatars $userAvatars,
public function __construct(Ldap $ldap, UserAvatars $userAvatars, GroupSyncService $groupSyncService) protected GroupSyncService $groupSyncService
{ ) {
$this->ldap = $ldap;
$this->userAvatars = $userAvatars;
$this->groupSyncService = $groupSyncService;
$this->config = config('services.ldap'); $this->config = config('services.ldap');
$this->enabled = config('auth.method') === 'ldap'; $this->enabled = config('auth.method') === 'ldap';
} }
@ -59,7 +52,7 @@ class LdapService
// Clean attributes // Clean attributes
foreach ($attributes as $index => $attribute) { foreach ($attributes as $index => $attribute) {
if (strpos($attribute, 'BIN;') === 0) { if (str_starts_with($attribute, 'BIN;')) {
$attributes[$index] = substr($attribute, strlen('BIN;')); $attributes[$index] = substr($attribute, strlen('BIN;'));
} }
} }
@ -82,7 +75,7 @@ class LdapService
* Get the details of a user from LDAP using the given username. * Get the details of a user from LDAP using the given username.
* User found via configurable user filter. * User found via configurable user filter.
* *
* @throws LdapException * @throws LdapException|JsonDebugException
*/ */
public function getUserDetails(string $userName): ?array public function getUserDetails(string $userName): ?array
{ {
@ -126,7 +119,7 @@ class LdapService
*/ */
protected function getUserResponseProperty(array $userDetails, string $propertyKey, $defaultValue) protected function getUserResponseProperty(array $userDetails, string $propertyKey, $defaultValue)
{ {
$isBinary = strpos($propertyKey, 'BIN;') === 0; $isBinary = str_starts_with($propertyKey, 'BIN;');
$propertyKey = strtolower($propertyKey); $propertyKey = strtolower($propertyKey);
$value = $defaultValue; $value = $defaultValue;
@ -170,11 +163,11 @@ class LdapService
* Bind the system user to the LDAP connection using the given credentials * Bind the system user to the LDAP connection using the given credentials
* otherwise anonymous access is attempted. * otherwise anonymous access is attempted.
* *
* @param resource $connection * @param resource|\LDAP\Connection $connection
* *
* @throws LdapException * @throws LdapException
*/ */
protected function bindSystemUser($connection) protected function bindSystemUser($connection): void
{ {
$ldapDn = $this->config['dn']; $ldapDn = $this->config['dn'];
$ldapPass = $this->config['pass']; $ldapPass = $this->config['pass'];
@ -197,7 +190,7 @@ class LdapService
* *
* @throws LdapException * @throws LdapException
* *
* @return resource * @return resource|\LDAP\Connection
*/ */
protected function getConnection() protected function getConnection()
{ {
@ -216,8 +209,8 @@ class LdapService
$this->ldap->setOption(null, LDAP_OPT_X_TLS_REQUIRE_CERT, LDAP_OPT_X_TLS_NEVER); $this->ldap->setOption(null, LDAP_OPT_X_TLS_REQUIRE_CERT, LDAP_OPT_X_TLS_NEVER);
} }
$serverDetails = $this->parseServerString($this->config['server']); $ldapHost = $this->parseServerString($this->config['server']);
$ldapConnection = $this->ldap->connect($serverDetails['host'], $serverDetails['port']); $ldapConnection = $this->ldap->connect($ldapHost);
if ($ldapConnection === false) { if ($ldapConnection === false) {
throw new LdapException(trans('errors.ldap_cannot_connect')); throw new LdapException(trans('errors.ldap_cannot_connect'));
@ -242,23 +235,16 @@ class LdapService
} }
/** /**
* Parse a LDAP server string and return the host and port for a connection. * Parse an LDAP server string and return the host suitable for a connection.
* Is flexible to formats such as 'ldap.example.com:8069' or 'ldaps://ldap.example.com'. * Is flexible to formats such as 'ldap.example.com:8069' or 'ldaps://ldap.example.com'.
*/ */
protected function parseServerString(string $serverString): array protected function parseServerString(string $serverString): string
{ {
$serverNameParts = explode(':', $serverString); if (str_starts_with($serverString, 'ldaps://') || str_starts_with($serverString, 'ldap://')) {
return $serverString;
// If we have a protocol just return the full string since PHP will ignore a separate port.
if ($serverNameParts[0] === 'ldaps' || $serverNameParts[0] === 'ldap') {
return ['host' => $serverString, 'port' => 389];
} }
// Otherwise, extract the port out return "ldap://{$serverString}";
$hostName = $serverNameParts[0];
$ldapPort = (count($serverNameParts) > 1) ? intval($serverNameParts[1]) : 389;
return ['host' => $hostName, 'port' => $ldapPort];
} }
/** /**
@ -386,7 +372,7 @@ class LdapService
* @throws LdapException * @throws LdapException
* @throws JsonDebugException * @throws JsonDebugException
*/ */
public function syncGroups(User $user, string $username) public function syncGroups(User $user, string $username): void
{ {
$userLdapGroups = $this->getUserGroups($username); $userLdapGroups = $this->getUserGroups($username);
$this->groupSyncService->syncUserWithFoundGroups($user, $userLdapGroups, $this->config['remove_from_groups']); $this->groupSyncService->syncUserWithFoundGroups($user, $userLdapGroups, $this->config['remove_from_groups']);

View File

@ -1,15 +1,15 @@
<?php <?php
namespace BookStack\Auth\Access; namespace BookStack\Access;
use BookStack\Actions\ActivityType; use BookStack\Access\Mfa\MfaSession;
use BookStack\Auth\Access\Mfa\MfaSession; use BookStack\Activity\ActivityType;
use BookStack\Auth\User;
use BookStack\Exceptions\LoginAttemptException; use BookStack\Exceptions\LoginAttemptException;
use BookStack\Exceptions\StoppedAuthenticationException; use BookStack\Exceptions\StoppedAuthenticationException;
use BookStack\Facades\Activity; use BookStack\Facades\Activity;
use BookStack\Facades\Theme; use BookStack\Facades\Theme;
use BookStack\Theming\ThemeEvents; use BookStack\Theming\ThemeEvents;
use BookStack\Users\Models\User;
use Exception; use Exception;
class LoginService class LoginService

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,6 +1,6 @@
<?php <?php
namespace BookStack\Auth\Access\Oidc; namespace BookStack\Access\Oidc;
use phpseclib3\Crypt\Common\PublicKey; use phpseclib3\Crypt\Common\PublicKey;
use phpseclib3\Crypt\PublicKeyLoader; use phpseclib3\Crypt\PublicKeyLoader;

View File

@ -1,6 +1,6 @@
<?php <?php
namespace BookStack\Auth\Access\Oidc; namespace BookStack\Access\Oidc;
use League\OAuth2\Client\Grant\AbstractGrant; use League\OAuth2\Client\Grant\AbstractGrant;
use League\OAuth2\Client\Provider\AbstractProvider; use League\OAuth2\Client\Provider\AbstractProvider;

View File

@ -1,6 +1,6 @@
<?php <?php
namespace BookStack\Auth\Access\Oidc; namespace BookStack\Access\Oidc;
use GuzzleHttp\Psr7\Request; use GuzzleHttp\Psr7\Request;
use Illuminate\Contracts\Cache\Repository; use Illuminate\Contracts\Cache\Repository;

View File

@ -1,16 +1,16 @@
<?php <?php
namespace BookStack\Auth\Access\Oidc; namespace BookStack\Access\Oidc;
use BookStack\Auth\Access\GroupSyncService; use BookStack\Access\GroupSyncService;
use BookStack\Auth\Access\LoginService; use BookStack\Access\LoginService;
use BookStack\Auth\Access\RegistrationService; use BookStack\Access\RegistrationService;
use BookStack\Auth\User;
use BookStack\Exceptions\JsonDebugException; use BookStack\Exceptions\JsonDebugException;
use BookStack\Exceptions\StoppedAuthenticationException; use BookStack\Exceptions\StoppedAuthenticationException;
use BookStack\Exceptions\UserRegistrationException; use BookStack\Exceptions\UserRegistrationException;
use BookStack\Facades\Theme; use BookStack\Facades\Theme;
use BookStack\Theming\ThemeEvents; use BookStack\Theming\ThemeEvents;
use BookStack\Users\Models\User;
use Illuminate\Support\Arr; use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Cache;
use League\OAuth2\Client\OptionProvider\HttpBasicAuthOptionProvider; use League\OAuth2\Client\OptionProvider\HttpBasicAuthOptionProvider;

View File

@ -1,15 +1,14 @@
<?php <?php
namespace BookStack\Auth\Access; namespace BookStack\Access;
use BookStack\Actions\ActivityType; use BookStack\Activity\ActivityType;
use BookStack\Auth\SocialAccount;
use BookStack\Auth\User;
use BookStack\Auth\UserRepo;
use BookStack\Exceptions\UserRegistrationException; use BookStack\Exceptions\UserRegistrationException;
use BookStack\Facades\Activity; use BookStack\Facades\Activity;
use BookStack\Facades\Theme; use BookStack\Facades\Theme;
use BookStack\Theming\ThemeEvents; use BookStack\Theming\ThemeEvents;
use BookStack\Users\Models\User;
use BookStack\Users\UserRepo;
use Exception; use Exception;
use Illuminate\Support\Str; use Illuminate\Support\Str;

View File

@ -1,12 +1,12 @@
<?php <?php
namespace BookStack\Auth\Access; namespace BookStack\Access;
use BookStack\Auth\User;
use BookStack\Exceptions\JsonDebugException; use BookStack\Exceptions\JsonDebugException;
use BookStack\Exceptions\SamlException; use BookStack\Exceptions\SamlException;
use BookStack\Exceptions\StoppedAuthenticationException; use BookStack\Exceptions\StoppedAuthenticationException;
use BookStack\Exceptions\UserRegistrationException; use BookStack\Exceptions\UserRegistrationException;
use BookStack\Users\Models\User;
use Exception; use Exception;
use OneLogin\Saml2\Auth; use OneLogin\Saml2\Auth;
use OneLogin\Saml2\Constants; use OneLogin\Saml2\Constants;

View File

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

View File

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

View File

@ -1,9 +1,9 @@
<?php <?php
namespace BookStack\Auth\Access; namespace BookStack\Access;
use BookStack\Auth\User;
use BookStack\Notifications\UserInvite; use BookStack\Notifications\UserInvite;
use BookStack\Users\Models\User;
class UserInviteService extends UserTokenService class UserInviteService extends UserTokenService
{ {

View File

@ -1,10 +1,10 @@
<?php <?php
namespace BookStack\Auth\Access; namespace BookStack\Access;
use BookStack\Auth\User;
use BookStack\Exceptions\UserTokenExpiredException; use BookStack\Exceptions\UserTokenExpiredException;
use BookStack\Exceptions\UserTokenNotFoundException; use BookStack\Exceptions\UserTokenNotFoundException;
use BookStack\Users\Models\User;
use Carbon\Carbon; use Carbon\Carbon;
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str; use Illuminate\Support\Str;

View File

@ -1,13 +1,14 @@
<?php <?php
namespace BookStack\Actions; namespace BookStack\Activity;
use BookStack\Auth\Permissions\PermissionApplicator; use BookStack\Activity\Models\Activity;
use BookStack\Auth\User;
use BookStack\Entities\Models\Book; use BookStack\Entities\Models\Book;
use BookStack\Entities\Models\Chapter; use BookStack\Entities\Models\Chapter;
use BookStack\Entities\Models\Entity; use BookStack\Entities\Models\Entity;
use BookStack\Entities\Models\Page; use BookStack\Entities\Models\Page;
use BookStack\Permissions\PermissionApplicator;
use BookStack\Users\Models\User;
use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Relations\Relation; use Illuminate\Database\Eloquent\Relations\Relation;

View File

@ -1,6 +1,6 @@
<?php <?php
namespace BookStack\Actions; namespace BookStack\Activity;
class ActivityType class ActivityType
{ {

View File

@ -1,32 +1,20 @@
<?php <?php
namespace BookStack\Actions; namespace BookStack\Activity;
use BookStack\Activity\Models\Comment;
use BookStack\Entities\Models\Entity; use BookStack\Entities\Models\Entity;
use BookStack\Facades\Activity as ActivityService; use BookStack\Facades\Activity as ActivityService;
use League\CommonMark\CommonMarkConverter; use League\CommonMark\CommonMarkConverter;
/**
* Class CommentRepo.
*/
class CommentRepo class CommentRepo
{ {
/**
* @var Comment
*/
protected $comment;
public function __construct(Comment $comment)
{
$this->comment = $comment;
}
/** /**
* Get a comment by ID. * Get a comment by ID.
*/ */
public function getById(int $id): Comment public function getById(int $id): Comment
{ {
return $this->comment->newQuery()->findOrFail($id); return Comment::query()->findOrFail($id);
} }
/** /**
@ -35,7 +23,7 @@ class CommentRepo
public function create(Entity $entity, string $text, ?int $parent_id): Comment public function create(Entity $entity, string $text, ?int $parent_id): Comment
{ {
$userId = user()->id; $userId = user()->id;
$comment = $this->comment->newInstance(); $comment = new Comment();
$comment->text = $text; $comment->text = $text;
$comment->html = $this->commentToHtml($text); $comment->html = $this->commentToHtml($text);
@ -82,7 +70,7 @@ class CommentRepo
'allow_unsafe_links' => false, 'allow_unsafe_links' => false,
]); ]);
return $converter->convertToHtml($commentText); return $converter->convert($commentText);
} }
/** /**
@ -90,9 +78,8 @@ class CommentRepo
*/ */
protected function getNextLocalId(Entity $entity): int protected function getNextLocalId(Entity $entity): int
{ {
/** @var Comment $comment */ $currentMaxId = $entity->comments()->max('local_id');
$comment = $entity->comments(false)->orderBy('local_id', 'desc')->first();
return ($comment->local_id ?? 0) + 1; return $currentMaxId + 1;
} }
} }

View File

@ -1,12 +1,12 @@
<?php <?php
namespace BookStack\Http\Controllers; namespace BookStack\Activity\Controllers;
use BookStack\Actions\Activity; use BookStack\Activity\ActivityType;
use BookStack\Actions\ActivityType; use BookStack\Activity\Models\Activity;
use BookStack\Http\Controller;
use BookStack\Util\SimpleListOptions; use BookStack\Util\SimpleListOptions;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
class AuditLogController extends Controller class AuditLogController extends Controller
{ {

View File

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

View File

@ -1,11 +1,12 @@
<?php <?php
namespace BookStack\Http\Controllers; namespace BookStack\Activity\Controllers;
use BookStack\Activity\Models\Favouritable;
use BookStack\App\Model;
use BookStack\Entities\Models\Entity; use BookStack\Entities\Models\Entity;
use BookStack\Entities\Queries\TopFavourites; use BookStack\Entities\Queries\TopFavourites;
use BookStack\Interfaces\Favouritable; use BookStack\Http\Controller;
use BookStack\Model;
use Illuminate\Http\Request; use Illuminate\Http\Request;
class FavouriteController extends Controller class FavouriteController extends Controller

View File

@ -1,8 +1,9 @@
<?php <?php
namespace BookStack\Http\Controllers; namespace BookStack\Activity\Controllers;
use BookStack\Actions\TagRepo; use BookStack\Activity\TagRepo;
use BookStack\Http\Controller;
use BookStack\Util\SimpleListOptions; use BookStack\Util\SimpleListOptions;
use Illuminate\Http\Request; use Illuminate\Http\Request;

View File

@ -1,10 +1,11 @@
<?php <?php
namespace BookStack\Http\Controllers; namespace BookStack\Activity\Controllers;
use BookStack\Actions\ActivityType; use BookStack\Activity\ActivityType;
use BookStack\Actions\Queries\WebhooksAllPaginatedAndSorted; use BookStack\Activity\Models\Webhook;
use BookStack\Actions\Webhook; use BookStack\Activity\Queries\WebhooksAllPaginatedAndSorted;
use BookStack\Http\Controller;
use BookStack\Util\SimpleListOptions; use BookStack\Util\SimpleListOptions;
use Illuminate\Http\Request; use Illuminate\Http\Request;

View File

@ -1,11 +1,13 @@
<?php <?php
namespace BookStack\Actions; namespace BookStack\Activity;
use BookStack\Auth\User; use BookStack\Activity\Models\Loggable;
use BookStack\Activity\Models\Webhook;
use BookStack\Activity\Tools\WebhookFormatter;
use BookStack\Facades\Theme; use BookStack\Facades\Theme;
use BookStack\Interfaces\Loggable;
use BookStack\Theming\ThemeEvents; use BookStack\Theming\ThemeEvents;
use BookStack\Users\Models\User;
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Foundation\Bus\Dispatchable;

View File

@ -1,11 +1,11 @@
<?php <?php
namespace BookStack\Actions; namespace BookStack\Activity\Models;
use BookStack\Auth\Permissions\JointPermission; use BookStack\App\Model;
use BookStack\Auth\User;
use BookStack\Entities\Models\Entity; use BookStack\Entities\Models\Entity;
use BookStack\Model; use BookStack\Permissions\Models\JointPermission;
use BookStack\Users\Models\User;
use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\MorphTo; use Illuminate\Database\Eloquent\Relations\MorphTo;
@ -19,6 +19,8 @@ use Illuminate\Support\Str;
* @property string $entity_type * @property string $entity_type
* @property int $entity_id * @property int $entity_id
* @property int $user_id * @property int $user_id
* @property Carbon $created_at
* @property Carbon $updated_at
*/ */
class Activity extends Model class Activity extends Model
{ {

View File

@ -1,9 +1,9 @@
<?php <?php
namespace BookStack\Actions; namespace BookStack\Activity\Models;
use BookStack\Model; use BookStack\App\Model;
use BookStack\Traits\HasCreatorAndUpdater; use BookStack\Users\Models\HasCreatorAndUpdater;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\MorphTo; use Illuminate\Database\Eloquent\Relations\MorphTo;

View File

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

View File

@ -1,9 +1,9 @@
<?php <?php
namespace BookStack\Actions; namespace BookStack\Activity\Models;
use BookStack\Auth\Permissions\JointPermission; use BookStack\App\Model;
use BookStack\Model; use BookStack\Permissions\Models\JointPermission;
use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\MorphTo; use Illuminate\Database\Eloquent\Relations\MorphTo;

View File

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

View File

@ -1,9 +1,9 @@
<?php <?php
namespace BookStack\Actions; namespace BookStack\Activity\Models;
use BookStack\Auth\Permissions\JointPermission; use BookStack\App\Model;
use BookStack\Model; use BookStack\Permissions\Models\JointPermission;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\MorphTo; use Illuminate\Database\Eloquent\Relations\MorphTo;

View File

@ -1,10 +1,9 @@
<?php <?php
namespace BookStack\Actions; namespace BookStack\Activity\Models;
use BookStack\Auth\Permissions\JointPermission; use BookStack\App\Model;
use BookStack\Interfaces\Viewable; use BookStack\Permissions\Models\JointPermission;
use BookStack\Model;
use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\MorphTo; use Illuminate\Database\Eloquent\Relations\MorphTo;
@ -55,12 +54,4 @@ class View extends Model
return $view->views; return $view->views;
} }
/**
* Clear all views from the system.
*/
public static function clearAll()
{
static::query()->truncate();
}
} }

View File

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

View File

@ -1,8 +1,8 @@
<?php <?php
namespace BookStack\Actions; namespace BookStack\Activity\Models;
use BookStack\Interfaces\Loggable; use BookStack\Activity\ActivityType;
use Carbon\Carbon; use Carbon\Carbon;
use Illuminate\Database\Eloquent\Collection; use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;

View File

@ -1,6 +1,6 @@
<?php <?php
namespace BookStack\Actions; namespace BookStack\Activity\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;

View File

@ -1,8 +1,8 @@
<?php <?php
namespace BookStack\Actions\Queries; namespace BookStack\Activity\Queries;
use BookStack\Actions\Webhook; use BookStack\Activity\Models\Webhook;
use BookStack\Util\SimpleListOptions; use BookStack\Util\SimpleListOptions;
use Illuminate\Pagination\LengthAwarePaginator; use Illuminate\Pagination\LengthAwarePaginator;

View File

@ -1,9 +1,10 @@
<?php <?php
namespace BookStack\Actions; namespace BookStack\Activity;
use BookStack\Auth\Permissions\PermissionApplicator; use BookStack\Activity\Models\Tag;
use BookStack\Entities\Models\Entity; use BookStack\Entities\Models\Entity;
use BookStack\Permissions\PermissionApplicator;
use BookStack\Util\SimpleListOptions; use BookStack\Util\SimpleListOptions;
use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;

View File

@ -1,10 +1,13 @@
<?php <?php
namespace BookStack\Actions; namespace BookStack\Activity\Tools;
use BookStack\Activity\DispatchWebhookJob;
use BookStack\Activity\Models\Activity;
use BookStack\Activity\Models\Loggable;
use BookStack\Activity\Models\Webhook;
use BookStack\Entities\Models\Entity; use BookStack\Entities\Models\Entity;
use BookStack\Facades\Theme; use BookStack\Facades\Theme;
use BookStack\Interfaces\Loggable;
use BookStack\Theming\ThemeEvents; use BookStack\Theming\ThemeEvents;
use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;

View File

@ -0,0 +1,102 @@
<?php
namespace BookStack\Activity\Tools;
use BookStack\Activity\Models\Comment;
use BookStack\Entities\Models\Page;
class CommentTree
{
/**
* The built nested tree structure array.
* @var array{comment: Comment, depth: int, children: array}[]
*/
protected array $tree;
protected array $comments;
public function __construct(
protected Page $page
) {
$this->comments = $this->loadComments();
$this->tree = $this->createTree($this->comments);
}
public function enabled(): bool
{
return !setting('app-disable-comments');
}
public function empty(): bool
{
return count($this->tree) === 0;
}
public function count(): int
{
return count($this->comments);
}
public function get(): array
{
return $this->tree;
}
/**
* @param Comment[] $comments
*/
protected function createTree(array $comments): array
{
$byId = [];
foreach ($comments as $comment) {
$byId[$comment->local_id] = $comment;
}
$childMap = [];
foreach ($comments as $comment) {
$parent = $comment->parent_id;
if (is_null($parent) || !isset($byId[$parent])) {
$parent = 0;
}
if (!isset($childMap[$parent])) {
$childMap[$parent] = [];
}
$childMap[$parent][] = $comment->local_id;
}
$tree = [];
foreach ($childMap[0] ?? [] as $childId) {
$tree[] = $this->createTreeForId($childId, 0, $byId, $childMap);
}
return $tree;
}
protected function createTreeForId(int $id, int $depth, array &$byId, array &$childMap): array
{
$childIds = $childMap[$id] ?? [];
$children = [];
foreach ($childIds as $childId) {
$children[] = $this->createTreeForId($childId, $depth + 1, $byId, $childMap);
}
return [
'comment' => $byId[$id],
'depth' => $depth,
'children' => $children,
];
}
protected function loadComments(): array
{
if (!$this->enabled()) {
return [];
}
return $this->page->comments()
->with('createdBy')
->get()
->all();
}
}

View File

@ -1,6 +1,6 @@
<?php <?php
namespace BookStack\Actions; namespace BookStack\Activity\Tools;
class IpFormatter class IpFormatter
{ {

View File

@ -1,6 +1,8 @@
<?php <?php
namespace BookStack\Actions; namespace BookStack\Activity\Tools;
use BookStack\Activity\Models\Tag;
class TagClassGenerator class TagClassGenerator
{ {

View File

@ -1,12 +1,14 @@
<?php <?php
namespace BookStack\Actions; namespace BookStack\Activity\Tools;
use BookStack\Auth\User; use BookStack\Activity\ActivityType;
use BookStack\Activity\Models\Loggable;
use BookStack\Activity\Models\Webhook;
use BookStack\App\Model;
use BookStack\Entities\Models\Entity; use BookStack\Entities\Models\Entity;
use BookStack\Entities\Models\Page; use BookStack\Entities\Models\Page;
use BookStack\Interfaces\Loggable; use BookStack\Users\Models\User;
use BookStack\Model;
use Illuminate\Support\Carbon; use Illuminate\Support\Carbon;
class WebhookFormatter class WebhookFormatter

View File

@ -1,8 +1,8 @@
<?php <?php
namespace BookStack\Http\Controllers\Api; namespace BookStack\Api;
use BookStack\Api\ApiDocsGenerator; use BookStack\Http\ApiController;
class ApiDocsController extends ApiController class ApiDocsController extends ApiController
{ {
@ -28,4 +28,12 @@ class ApiDocsController extends ApiController
return response()->json($docs); return response()->json($docs);
} }
/**
* Redirect to the API docs page.
*/
public function redirect()
{
return redirect('/api/docs');
}
} }

View File

@ -2,7 +2,7 @@
namespace BookStack\Api; namespace BookStack\Api;
use BookStack\Http\Controllers\Api\ApiController; use BookStack\Http\ApiController;
use Exception; use Exception;
use Illuminate\Contracts\Container\BindingResolutionException; use Illuminate\Contracts\Container\BindingResolutionException;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
@ -16,8 +16,8 @@ use ReflectionMethod;
class ApiDocsGenerator class ApiDocsGenerator
{ {
protected $reflectionClasses = []; protected array $reflectionClasses = [];
protected $controllerClasses = []; protected array $controllerClasses = [];
/** /**
* Load the docs form the cache if existing * Load the docs form the cache if existing
@ -139,9 +139,10 @@ class ApiDocsGenerator
protected function parseDescriptionFromMethodComment(string $comment): string protected function parseDescriptionFromMethodComment(string $comment): string
{ {
$matches = []; $matches = [];
preg_match_all('/^\s*?\*\s((?![@\s]).*?)$/m', $comment, $matches); preg_match_all('/^\s*?\*\s?($|((?![\/@\s]).*?))$/m', $comment, $matches);
return implode(' ', $matches[1] ?? []); $text = implode(' ', $matches[1] ?? []);
return str_replace(' ', "\n", $text);
} }
/** /**

View File

@ -2,8 +2,8 @@
namespace BookStack\Api; namespace BookStack\Api;
use BookStack\Auth\User; use BookStack\Activity\Models\Loggable;
use BookStack\Interfaces\Loggable; use BookStack\Users\Models\User;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Support\Carbon; use Illuminate\Support\Carbon;

View File

@ -2,7 +2,7 @@
namespace BookStack\Api; namespace BookStack\Api;
use BookStack\Auth\Access\LoginService; use BookStack\Access\LoginService;
use BookStack\Exceptions\ApiAuthException; use BookStack\Exceptions\ApiAuthException;
use Illuminate\Auth\GuardHelpers; use Illuminate\Auth\GuardHelpers;
use Illuminate\Contracts\Auth\Authenticatable; use Illuminate\Contracts\Auth\Authenticatable;

View File

@ -1,10 +1,10 @@
<?php <?php
namespace BookStack\Http\Controllers; namespace BookStack\Api;
use BookStack\Actions\ActivityType; use BookStack\Activity\ActivityType;
use BookStack\Api\ApiToken; use BookStack\Http\Controller;
use BookStack\Auth\User; use BookStack\Users\Models\User;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str; use Illuminate\Support\Str;
@ -58,7 +58,6 @@ class UserApiTokenController extends Controller
$token->save(); $token->save();
session()->flash('api-token-secret:' . $token->id, $secret); session()->flash('api-token-secret:' . $token->id, $secret);
$this->showSuccessNotification(trans('settings.user_api_token_create_success'));
$this->logActivity(ActivityType::API_TOKEN_CREATE, $token); $this->logActivity(ActivityType::API_TOKEN_CREATE, $token);
return redirect($user->getEditUrl('/api-tokens/' . $token->id)); return redirect($user->getEditUrl('/api-tokens/' . $token->id));
@ -96,7 +95,6 @@ class UserApiTokenController extends Controller
'expires_at' => $request->get('expires_at') ?: ApiToken::defaultExpiry(), 'expires_at' => $request->get('expires_at') ?: ApiToken::defaultExpiry(),
])->save(); ])->save();
$this->showSuccessNotification(trans('settings.user_api_token_update_success'));
$this->logActivity(ActivityType::API_TOKEN_UPDATE, $token); $this->logActivity(ActivityType::API_TOKEN_UPDATE, $token);
return redirect($user->getEditUrl('/api-tokens/' . $token->id)); return redirect($user->getEditUrl('/api-tokens/' . $token->id));
@ -123,7 +121,6 @@ class UserApiTokenController extends Controller
[$user, $token] = $this->checkPermissionAndFetchUserToken($userId, $tokenId); [$user, $token] = $this->checkPermissionAndFetchUserToken($userId, $tokenId);
$token->delete(); $token->delete();
$this->showSuccessNotification(trans('settings.user_api_token_delete_success'));
$this->logActivity(ActivityType::API_TOKEN_DELETE, $token); $this->logActivity(ActivityType::API_TOKEN_DELETE, $token);
return redirect($user->getEditUrl('#api_tokens')); return redirect($user->getEditUrl('#api_tokens'));

View File

@ -1,6 +1,6 @@
<?php <?php
namespace BookStack; namespace BookStack\App;
class Application extends \Illuminate\Foundation\Application class Application extends \Illuminate\Foundation\Application
{ {

View File

@ -1,8 +1,8 @@
<?php <?php
namespace BookStack\Http\Controllers; namespace BookStack\App;
use BookStack\Actions\ActivityQueries; use BookStack\Activity\ActivityQueries;
use BookStack\Entities\Models\Book; use BookStack\Entities\Models\Book;
use BookStack\Entities\Models\Page; use BookStack\Entities\Models\Page;
use BookStack\Entities\Queries\RecentlyViewed; use BookStack\Entities\Queries\RecentlyViewed;
@ -10,6 +10,7 @@ use BookStack\Entities\Queries\TopFavourites;
use BookStack\Entities\Repos\BookRepo; use BookStack\Entities\Repos\BookRepo;
use BookStack\Entities\Repos\BookshelfRepo; use BookStack\Entities\Repos\BookshelfRepo;
use BookStack\Entities\Tools\PageContent; use BookStack\Entities\Tools\PageContent;
use BookStack\Http\Controller;
use BookStack\Uploads\FaviconHandler; use BookStack\Uploads\FaviconHandler;
use BookStack\Util\SimpleListOptions; use BookStack\Util\SimpleListOptions;
use Illuminate\Http\Request; use Illuminate\Http\Request;

View File

@ -1,6 +1,6 @@
<?php <?php
namespace BookStack; namespace BookStack\App;
use Illuminate\Database\Eloquent\Model as EloquentModel; use Illuminate\Database\Eloquent\Model as EloquentModel;

View File

@ -1,9 +1,9 @@
<?php <?php
namespace BookStack\Providers; namespace BookStack\App\Providers;
use BookStack\Actions\ActivityLogger; use BookStack\Access\SocialAuthService;
use BookStack\Auth\Access\SocialAuthService; use BookStack\Activity\Tools\ActivityLogger;
use BookStack\Entities\Models\Book; use BookStack\Entities\Models\Book;
use BookStack\Entities\Models\Bookshelf; use BookStack\Entities\Models\Bookshelf;
use BookStack\Entities\Models\Chapter; use BookStack\Entities\Models\Chapter;

View File

@ -1,14 +1,14 @@
<?php <?php
namespace BookStack\Providers; namespace BookStack\App\Providers;
use BookStack\Access\ExternalBaseUserProvider;
use BookStack\Access\Guards\AsyncExternalBaseSessionGuard;
use BookStack\Access\Guards\LdapSessionGuard;
use BookStack\Access\LdapService;
use BookStack\Access\LoginService;
use BookStack\Access\RegistrationService;
use BookStack\Api\ApiTokenGuard; use BookStack\Api\ApiTokenGuard;
use BookStack\Auth\Access\ExternalBaseUserProvider;
use BookStack\Auth\Access\Guards\AsyncExternalBaseSessionGuard;
use BookStack\Auth\Access\Guards\LdapSessionGuard;
use BookStack\Auth\Access\LdapService;
use BookStack\Auth\Access\LoginService;
use BookStack\Auth\Access\RegistrationService;
use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Auth;
use Illuminate\Support\ServiceProvider; use Illuminate\Support\ServiceProvider;
use Illuminate\Validation\Rules\Password; use Illuminate\Validation\Rules\Password;

View File

@ -1,6 +1,6 @@
<?php <?php
namespace BookStack\Providers; namespace BookStack\App\Providers;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider; use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
use SocialiteProviders\Manager\SocialiteWasCalled; use SocialiteProviders\Manager\SocialiteWasCalled;

View File

@ -1,6 +1,6 @@
<?php <?php
namespace BookStack\Providers; namespace BookStack\App\Providers;
use Illuminate\Cache\RateLimiting\Limit; use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider; use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;

View File

@ -1,6 +1,6 @@
<?php <?php
namespace BookStack\Providers; namespace BookStack\App\Providers;
use BookStack\Theming\ThemeEvents; use BookStack\Theming\ThemeEvents;
use BookStack\Theming\ThemeService; use BookStack\Theming\ThemeService;

View File

@ -1,6 +1,6 @@
<?php <?php
namespace BookStack\Providers; namespace BookStack\App\Providers;
use BookStack\Translation\FileLoader; use BookStack\Translation\FileLoader;
use BookStack\Translation\MessageSelector; use BookStack\Translation\MessageSelector;

View File

@ -1,6 +1,6 @@
<?php <?php
namespace BookStack\Providers; namespace BookStack\App\Providers;
use BookStack\Uploads\ImageService; use BookStack\Uploads\ImageService;
use Illuminate\Support\Facades\Validator; use Illuminate\Support\Facades\Validator;

View File

@ -1,6 +1,6 @@
<?php <?php
namespace BookStack\Providers; namespace BookStack\App\Providers;
use BookStack\Entities\BreadcrumbsViewComposer; use BookStack\Entities\BreadcrumbsViewComposer;
use Illuminate\Pagination\Paginator; use Illuminate\Pagination\Paginator;

View File

@ -1,6 +1,6 @@
<?php <?php
namespace BookStack\Interfaces; namespace BookStack\App;
/** /**
* Assigned to models that can have slugs. * Assigned to models that can have slugs.

View File

@ -1,9 +1,9 @@
<?php <?php
use BookStack\Auth\Permissions\PermissionApplicator; use BookStack\App\Model;
use BookStack\Auth\User; use BookStack\Permissions\PermissionApplicator;
use BookStack\Model;
use BookStack\Settings\SettingService; use BookStack\Settings\SettingService;
use BookStack\Users\Models\User;
/** /**
* Get the path to a versioned file. * Get the path to a versioned file.

View File

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

View File

@ -139,14 +139,14 @@ return [
SocialiteProviders\Manager\ServiceProvider::class, SocialiteProviders\Manager\ServiceProvider::class,
// BookStack custom service providers // BookStack custom service providers
BookStack\Providers\ThemeServiceProvider::class, \BookStack\App\Providers\ThemeServiceProvider::class,
BookStack\Providers\AppServiceProvider::class, \BookStack\App\Providers\AppServiceProvider::class,
BookStack\Providers\AuthServiceProvider::class, \BookStack\App\Providers\AuthServiceProvider::class,
BookStack\Providers\EventServiceProvider::class, \BookStack\App\Providers\EventServiceProvider::class,
BookStack\Providers\RouteServiceProvider::class, \BookStack\App\Providers\RouteServiceProvider::class,
BookStack\Providers\TranslationServiceProvider::class, \BookStack\App\Providers\TranslationServiceProvider::class,
BookStack\Providers\ValidationRuleServiceProvider::class, \BookStack\App\Providers\ValidationRuleServiceProvider::class,
BookStack\Providers\ViewTweaksServiceProvider::class, \BookStack\App\Providers\ViewTweaksServiceProvider::class,
], ],
// Class Aliases // Class Aliases

View File

@ -59,12 +59,12 @@ return [
'providers' => [ 'providers' => [
'users' => [ 'users' => [
'driver' => 'eloquent', 'driver' => 'eloquent',
'model' => \BookStack\Auth\User::class, 'model' => \BookStack\Users\Models\User::class,
], ],
'external' => [ 'external' => [
'driver' => 'external-users', 'driver' => 'external-users',
'model' => \BookStack\Auth\User::class, 'model' => \BookStack\Users\Models\User::class,
], ],
// 'users' => [ // 'users' => [

View File

@ -8,6 +8,10 @@
* Do not edit this file unless you're happy to maintain any changes yourself. * Do not edit this file unless you're happy to maintain any changes yourself.
*/ */
// Configured mail encryption method.
// STARTTLS should still be attempted, but tls/ssl forces TLS usage.
$mailEncryption = env('MAIL_ENCRYPTION', null);
return [ return [
// Mail driver to use. // Mail driver to use.
@ -27,9 +31,9 @@ return [
'mailers' => [ 'mailers' => [
'smtp' => [ 'smtp' => [
'transport' => 'smtp', 'transport' => 'smtp',
'scheme' => ($mailEncryption === 'tls' || $mailEncryption === 'ssl') ? 'smtps' : null,
'host' => env('MAIL_HOST', 'smtp.mailgun.org'), 'host' => env('MAIL_HOST', 'smtp.mailgun.org'),
'port' => env('MAIL_PORT', 587), 'port' => env('MAIL_PORT', 587),
'encryption' => env('MAIL_ENCRYPTION', 'tls'),
'username' => env('MAIL_USERNAME'), 'username' => env('MAIL_USERNAME'),
'password' => env('MAIL_PASSWORD'), 'password' => env('MAIL_PASSWORD'),
'verify_peer' => env('MAIL_VERIFY_SSL', true), 'verify_peer' => env('MAIL_VERIFY_SSL', true),

View File

@ -6,7 +6,7 @@ use BookStack\Uploads\ImageService;
use Illuminate\Console\Command; use Illuminate\Console\Command;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
class CleanupImages extends Command class CleanupImagesCommand extends Command
{ {
/** /**
* The name and signature of the console command. * The name and signature of the console command.
@ -25,60 +25,49 @@ class CleanupImages extends Command
*/ */
protected $description = 'Cleanup images and drawings'; protected $description = 'Cleanup images and drawings';
protected $imageService;
/**
* Create a new command instance.
*
* @param \BookStack\Uploads\ImageService $imageService
*/
public function __construct(ImageService $imageService)
{
$this->imageService = $imageService;
parent::__construct();
}
/** /**
* Execute the console command. * Execute the console command.
*
* @return mixed
*/ */
public function handle() public function handle(ImageService $imageService): int
{ {
$checkRevisions = $this->option('all') ? false : true; $checkRevisions = !$this->option('all');
$dryRun = $this->option('force') ? false : true; $dryRun = !$this->option('force');
if (!$dryRun) { if (!$dryRun) {
$proceed = $this->confirm("This operation is destructive and is not guaranteed to be fully accurate.\nEnsure you have a backup of your images.\nAre you sure you want to proceed?"); $this->warn("This operation is destructive and is not guaranteed to be fully accurate.\nEnsure you have a backup of your images.\n");
$proceed = $this->confirm("Are you sure you want to proceed?");
if (!$proceed) { if (!$proceed) {
return; return 0;
} }
} }
$deleted = $this->imageService->deleteUnusedImages($checkRevisions, $dryRun); $deleted = $imageService->deleteUnusedImages($checkRevisions, $dryRun);
$deleteCount = count($deleted); $deleteCount = count($deleted);
if ($dryRun) { if ($dryRun) {
$this->comment('Dry run, No images have been deleted'); $this->comment('Dry run, no images have been deleted');
$this->comment($deleteCount . ' images found that would have been deleted'); $this->comment($deleteCount . ' images found that would have been deleted');
$this->showDeletedImages($deleted); $this->showDeletedImages($deleted);
$this->comment('Run with -f or --force to perform deletions'); $this->comment('Run with -f or --force to perform deletions');
return; return 0;
} }
$this->showDeletedImages($deleted); $this->showDeletedImages($deleted);
$this->comment($deleteCount . ' images deleted'); $this->comment($deleteCount . ' images deleted');
return 0;
} }
protected function showDeletedImages($paths) protected function showDeletedImages($paths): void
{ {
if ($this->getOutput()->getVerbosity() <= OutputInterface::VERBOSITY_NORMAL) { if ($this->getOutput()->getVerbosity() <= OutputInterface::VERBOSITY_NORMAL) {
return; return;
} }
if (count($paths) > 0) { if (count($paths) > 0) {
$this->line('Images to delete:'); $this->line('Images to delete:');
} }
foreach ($paths as $path) { foreach ($paths as $path) {
$this->line($path); $this->line($path);
} }

View File

@ -2,10 +2,10 @@
namespace BookStack\Console\Commands; namespace BookStack\Console\Commands;
use BookStack\Actions\Activity; use BookStack\Activity\Models\Activity;
use Illuminate\Console\Command; use Illuminate\Console\Command;
class ClearActivity extends Command class ClearActivityCommand extends Command
{ {
/** /**
* The name and signature of the console command. * The name and signature of the console command.
@ -21,27 +21,13 @@ class ClearActivity extends Command
*/ */
protected $description = 'Clear user activity from the system'; protected $description = 'Clear user activity from the system';
protected $activity;
/**
* Create a new command instance.
*
* @param Activity $activity
*/
public function __construct(Activity $activity)
{
$this->activity = $activity;
parent::__construct();
}
/** /**
* Execute the console command. * Execute the console command.
*
* @return mixed
*/ */
public function handle() public function handle(): int
{ {
$this->activity->newQuery()->truncate(); Activity::query()->truncate();
$this->comment('System activity cleared'); $this->comment('System activity cleared');
return 0;
} }
} }

View File

@ -5,7 +5,7 @@ namespace BookStack\Console\Commands;
use BookStack\Entities\Models\PageRevision; use BookStack\Entities\Models\PageRevision;
use Illuminate\Console\Command; use Illuminate\Console\Command;
class ClearRevisions extends Command class ClearRevisionsCommand extends Command
{ {
/** /**
* The name and signature of the console command. * The name and signature of the console command.
@ -23,28 +23,14 @@ class ClearRevisions extends Command
*/ */
protected $description = 'Clear page revisions'; protected $description = 'Clear page revisions';
protected $pageRevision;
/**
* Create a new command instance.
*
* @param PageRevision $pageRevision
*/
public function __construct(PageRevision $pageRevision)
{
$this->pageRevision = $pageRevision;
parent::__construct();
}
/** /**
* Execute the console command. * Execute the console command.
*
* @return mixed
*/ */
public function handle() public function handle(): int
{ {
$deleteTypes = $this->option('all') ? ['version', 'update_draft'] : ['version']; $deleteTypes = $this->option('all') ? ['version', 'update_draft'] : ['version'];
$this->pageRevision->newQuery()->whereIn('type', $deleteTypes)->delete(); PageRevision::query()->whereIn('type', $deleteTypes)->delete();
$this->comment('Revisions deleted'); $this->comment('Revisions deleted');
return 0;
} }
} }

View File

@ -2,10 +2,10 @@
namespace BookStack\Console\Commands; namespace BookStack\Console\Commands;
use BookStack\Actions\View; use BookStack\Activity\Models\View;
use Illuminate\Console\Command; use Illuminate\Console\Command;
class ClearViews extends Command class ClearViewsCommand extends Command
{ {
/** /**
* The name and signature of the console command. * The name and signature of the console command.
@ -21,22 +21,13 @@ class ClearViews extends Command
*/ */
protected $description = 'Clear all view-counts for all entities'; protected $description = 'Clear all view-counts for all entities';
/**
* Create a new command instance.
*/
public function __construct()
{
parent::__construct();
}
/** /**
* Execute the console command. * Execute the console command.
*
* @return mixed
*/ */
public function handle() public function handle(): int
{ {
View::clearAll(); View::query()->truncate();
$this->comment('Views cleared'); $this->comment('Views cleared');
return 0;
} }
} }

View File

@ -6,7 +6,7 @@ use BookStack\Entities\Models\Bookshelf;
use BookStack\Entities\Tools\PermissionsUpdater; use BookStack\Entities\Tools\PermissionsUpdater;
use Illuminate\Console\Command; use Illuminate\Console\Command;
class CopyShelfPermissions extends Command class CopyShelfPermissionsCommand extends Command
{ {
/** /**
* The name and signature of the console command. * The name and signature of the console command.
@ -25,25 +25,10 @@ class CopyShelfPermissions extends Command
*/ */
protected $description = 'Copy shelf permissions to all child books'; protected $description = 'Copy shelf permissions to all child books';
protected PermissionsUpdater $permissionsUpdater;
/**
* Create a new command instance.
*
* @return void
*/
public function __construct(PermissionsUpdater $permissionsUpdater)
{
$this->permissionsUpdater = $permissionsUpdater;
parent::__construct();
}
/** /**
* Execute the console command. * Execute the console command.
*
* @return mixed
*/ */
public function handle() public function handle(PermissionsUpdater $permissionsUpdater): int
{ {
$shelfSlug = $this->option('slug'); $shelfSlug = $this->option('slug');
$cascadeAll = $this->option('all'); $cascadeAll = $this->option('all');
@ -52,7 +37,7 @@ class CopyShelfPermissions extends Command
if (!$cascadeAll && !$shelfSlug) { if (!$cascadeAll && !$shelfSlug) {
$this->error('Either a --slug or --all option must be provided.'); $this->error('Either a --slug or --all option must be provided.');
return; return 1;
} }
if ($cascadeAll) { if ($cascadeAll) {
@ -63,7 +48,7 @@ class CopyShelfPermissions extends Command
); );
if (!$continue && !$this->hasOption('no-interaction')) { if (!$continue && !$this->hasOption('no-interaction')) {
return; return 0;
} }
$shelves = Bookshelf::query()->get(['id']); $shelves = Bookshelf::query()->get(['id']);
@ -77,10 +62,11 @@ class CopyShelfPermissions extends Command
} }
foreach ($shelves as $shelf) { foreach ($shelves as $shelf) {
$this->permissionsUpdater->updateBookPermissionsFromShelf($shelf, false); $permissionsUpdater->updateBookPermissionsFromShelf($shelf, false);
$this->info('Copied permissions for shelf [' . $shelf->id . ']'); $this->info('Copied permissions for shelf [' . $shelf->id . ']');
} }
$this->info('Permissions copied for ' . $shelves->count() . ' shelves.'); $this->info('Permissions copied for ' . $shelves->count() . ' shelves.');
return 0;
} }
} }

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