namespace BookStack\Access\Guards;
/**
- * Saml2 Session Guard.
+ * External Auth Session Guard.
*
- * The saml2 login process is async in nature meaning it does not fit very well
- * into the default laravel 'Guard' auth flow. Instead most of the logic is done
- * via the Saml2 controller & Saml2Service. This class provides a safer, thin
- * version of SessionGuard.
+ * 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.
- *
- * @param array $credentials
- *
- * @return bool
*/
- public function validate(array $credentials = [])
+ public function validate(array $credentials = []): bool
{
return false;
}
/**
* Attempt to authenticate a user using the given credentials.
*
- * @param array $credentials
* @param bool $remember
- *
- * @return bool
*/
- public function attempt(array $credentials = [], $remember = false)
+ public function attempt(array $credentials = [], $remember = false): bool
{
return false;
}
/**
* Validate a user's credentials.
*
- * @param array $credentials
- *
* @throws LdapException
- *
- * @return bool
*/
- public function validate(array $credentials = [])
+ public function validate(array $credentials = []): bool
{
$userDetails = $this->ldapService->getUserDetails($credentials['username']);
{
$value = session()->get(self::LAST_LOGIN_ATTEMPTED_SESSION_KEY);
if (!$value) {
- return ['user_id' => null, 'method' => null];
+ return ['user_id' => null, 'method' => null, 'remember' => false];
}
[$id, $method, $remember, $time] = explode(':', $value);
if ($time < $hourAgo) {
$this->clearLastLoginAttempted();
- return ['user_id' => null, 'method' => null];
+ return ['user_id' => null, 'method' => null, 'remember' => false];
}
return ['user_id' => $id, 'method' => $method, 'remember' => boolval($remember)];
}
/**
- * Set the last login attempted user.
+ * 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.
+ * achieved, but a secondary factor has stopped the login.
*/
- protected function setLastLoginAttemptedForUser(User $user, string $method, bool $remember)
+ protected function setLastLoginAttemptedForUser(User $user, string $method, bool $remember): void
{
session()->put(
self::LAST_LOGIN_ATTEMPTED_SESSION_KEY,
use BookStack\Exceptions\NotFoundException;
use Illuminate\Database\Eloquent\Builder;
+/**
+ * @implements ProvidesEntityQueries<Book>
+ */
class BookQueries implements ProvidesEntityQueries
{
protected static array $listAttributes = [
use BookStack\Exceptions\NotFoundException;
use Illuminate\Database\Eloquent\Builder;
+/**
+ * @implements ProvidesEntityQueries<Bookshelf>
+ */
class BookshelfQueries implements ProvidesEntityQueries
{
protected static array $listAttributes = [
use BookStack\Exceptions\NotFoundException;
use Illuminate\Database\Eloquent\Builder;
+/**
+ * @implements ProvidesEntityQueries<Chapter>
+ */
class ChapterQueries implements ProvidesEntityQueries
{
protected static array $listAttributes = [
use BookStack\Exceptions\NotFoundException;
use Illuminate\Database\Eloquent\Builder;
+/**
+ * @implements ProvidesEntityQueries<Page>
+ */
class PageQueries implements ProvidesEntityQueries
{
protected static array $contentAttributes = [
'template', 'text', 'created_at', 'updated_at', 'priority', 'owned_by',
];
+ /**
+ * @return Builder<Page>
+ */
public function start(): Builder
{
return Page::query();
/**
* Interface for our classes which provide common queries for our
- * entity objects. Ideally all queries for entities should run through
+ * entity objects. Ideally, all queries for entities should run through
* these classes.
* Any added methods should return a builder instances to allow extension
* via building on the query, unless the method starts with 'find'
* in which case an entity object should be returned.
* (nullable unless it's a *OrFail method).
+ *
+ * @template TModel of Entity
*/
interface ProvidesEntityQueries
{
/**
* Start a new query for this entity type.
+ * @return Builder<TModel>
*/
public function start(): Builder;
/**
* Start a query for items that are visible, with selection
* configured for list display of this item.
- * @return Builder<Entity>
+ * @return Builder<TModel>
*/
public function visibleForList(): Builder;
}
protected static string $includeTagRegex = "/{{@\s?([0-9].*?)}}/";
/**
- * Elements to clean up and remove if left empty after a parsing operation.
- * @var DOMElement[]
+ * Nodes to clean up and remove if left empty after a parsing operation.
+ * @var DOMNode[]
*/
protected array $toCleanup = [];
}
/**
- * Cleanup after a parse operation.
+ * Clean up after a parse operation.
* Removes stranded elements we may have left during the parse.
*/
protected function cleanup(): void
namespace BookStack\Exceptions;
-use Exception;
use Illuminate\Auth\AuthenticationException;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Illuminate\Http\Response;
use Illuminate\Validation\ValidationException;
use Symfony\Component\ErrorHandler\Error\FatalError;
+use Symfony\Component\HttpFoundation\Response as SymfonyResponse;
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
use Throwable;
/**
* A list of the exception types that are not reported.
*
- * @var array<int, class-string<\Throwable>>
+ * @var array<int, class-string<Throwable>>
*/
protected $dontReport = [
NotFoundException::class,
/**
* Report or log an exception.
*
- * @param \Throwable $exception
- *
- * @throws \Throwable
+ * @param Throwable $exception
*
* @return void
+ *@throws Throwable
+ *
*/
public function report(Throwable $exception)
{
/**
* Render an exception into an HTTP response.
*
- * @param \Illuminate\Http\Request $request
- * @param Exception $e
- *
- * @return \Illuminate\Http\Response
+ * @param Request $request
*/
- public function render($request, Throwable $e)
+ public function render($request, Throwable $e): SymfonyResponse
{
if ($e instanceof FatalError && str_contains($e->getMessage(), 'bytes exhausted (tried to allocate') && $this->onOutOfMemory) {
$response = call_user_func($this->onOutOfMemory);
/**
* Convert an authentication exception into an unauthenticated response.
*
- * @param \Illuminate\Http\Request $request
- * @param \Illuminate\Auth\AuthenticationException $exception
- *
- * @return \Illuminate\Http\Response
+ * @param Request $request
*/
- protected function unauthenticated($request, AuthenticationException $exception)
+ protected function unauthenticated($request, AuthenticationException $exception): SymfonyResponse
{
if ($request->expectsJson()) {
return response()->json(['error' => 'Unauthenticated.'], 401);
/**
* Convert a validation exception into a JSON response.
*
- * @param \Illuminate\Http\Request $request
- * @param \Illuminate\Validation\ValidationException $exception
- *
- * @return \Illuminate\Http\JsonResponse
+ * @param Request $request
*/
- protected function invalidJson($request, ValidationException $exception)
+ protected function invalidJson($request, ValidationException $exception): JsonResponse
{
return response()->json($exception->errors(), $exception->status);
}
}
/**
- * @param array<string, array<string, int>> $permitsByType
+ * @param array<string, array<int, string>> $permitsByType
*/
protected function evaluatePermitsByType(array $permitsByType): ?int
{
/**
* @param string[] $typeIdChain
* @param array<string, EntityPermission[]> $permissionMapByTypeId
- * @return array<string, array<string, int>>
+ * @return array<string, array<int, string>>
*/
protected function collapseAndCategorisePermissions(array $typeIdChain, array $permissionMapByTypeId): array
{