Skip to content

Commit

Permalink
Merge branch 'release' into vatger
Browse files Browse the repository at this point in the history
  • Loading branch information
paulhollmann committed Jun 22, 2024
2 parents a020991 + 883ea5b commit 8251df4
Show file tree
Hide file tree
Showing 926 changed files with 15,286 additions and 7,673 deletions.
12 changes: 11 additions & 1 deletion .env.example.complete
Original file line number Diff line number Diff line change
Expand Up @@ -215,10 +215,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
Expand Down Expand Up @@ -267,6 +268,7 @@ 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
Expand Down Expand Up @@ -324,6 +326,14 @@ FILE_UPLOAD_SIZE_LIMIT=50
# 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

# 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
Expand Down
45 changes: 43 additions & 2 deletions .github/translators.txt
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,7 @@ 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
David Bauer (davbauer) :: German; German Informal
Guttorm Hveem (guttormhveem) :: Norwegian Nynorsk; Norwegian Bokmal
Minh Giang Truong (minhgiang1204) :: Vietnamese
Ioannis Ioannides (i.ioannides) :: Greek
Expand All @@ -374,7 +374,7 @@ balmag :: Hungarian
Antti-Jussi Nygård (ajnyga) :: Finnish
Eduard Ereza Martínez (Ereza) :: Catalan
Jabir Lang (amar.almrad) :: Arabic
Jaroslav Koblizek (foretix) :: Czech; French
Jaroslav Kobližek (foretix) :: Czech; French
Wiktor Adamczyk (adamczyk.wiktor) :: Polish
Abdulmajeed Alshuaibi (4Majeed) :: Arabic
NotSmartZakk :: Czech
Expand All @@ -388,3 +388,44 @@ 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
6 changes: 3 additions & 3 deletions .github/workflows/analyse-php.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: 8.1
php-version: 8.3
extensions: gd, mbstring, json, curl, xml, mysql, ldap

- name: Get Composer Cache Directory
Expand All @@ -27,10 +27,10 @@ jobs:
echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
- name: Cache composer packages
uses: actions/cache@v3
uses: actions/cache@v4
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-8.1
key: ${{ runner.os }}-composer-8.3
restore-keys: ${{ runner.os }}-composer-

- name: Install composer dependencies
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/test-migrations.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
runs-on: ubuntu-22.04
strategy:
matrix:
php: ['8.0', '8.1', '8.2', '8.3']
php: ['8.1', '8.2', '8.3']
steps:
- uses: actions/checkout@v1

Expand All @@ -32,7 +32,7 @@ jobs:
echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
- name: Cache composer packages
uses: actions/cache@v3
uses: actions/cache@v4
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ matrix.php }}
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/test-php.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
runs-on: ubuntu-22.04
strategy:
matrix:
php: ['8.0', '8.1', '8.2', '8.3']
php: ['8.1', '8.2', '8.3']
steps:
- uses: actions/checkout@v1

Expand All @@ -32,7 +32,7 @@ jobs:
echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
- name: Cache composer packages
uses: actions/cache@v3
uses: actions/cache@v4
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ matrix.php }}
Expand Down
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
The MIT License (MIT)

Copyright (c) 2015-2023, Dan Brown and the BookStack Project contributors.
Copyright (c) 2015-2024, 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
Expand Down
25 changes: 17 additions & 8 deletions app/Access/Controllers/ConfirmEmailController.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,17 @@ public function show()

/**
* Shows a notice that a user's email address has not been confirmed,
* Also has the option to re-send the confirmation email.
* 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.user-unconfirmed', ['user' => $user]);
return view('auth.register-confirm-awaiting');
}

/**
Expand Down Expand Up @@ -90,19 +94,24 @@ public function confirm(Request $request)
/**
* Resend the confirmation email.
*/
public function resend(Request $request)
public function resend()
{
$this->validate($request, [
'email' => ['required', 'email', 'exists:users,email'],
]);
$user = $this->userRepo->getByEmail($request->get('email'));
$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/confirm');
return redirect('/register/awaiting');
}

$this->showSuccessNotification(trans('auth.email_confirm_resent'));
Expand Down
5 changes: 5 additions & 0 deletions app/Access/Controllers/ForgotPasswordController.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use BookStack\Http\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Password;
use Illuminate\Support\Sleep;

class ForgotPasswordController extends Controller
{
Expand All @@ -32,6 +33,10 @@ public function sendResetLinkEmail(Request $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.
Expand Down
2 changes: 1 addition & 1 deletion app/Access/Controllers/HandlesPartialLogins.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ protected function currentOrLastAttemptedUser(): User
$user = auth()->user() ?? $loginService->getLastLoginAttemptUser();

if (!$user) {
throw new NotFoundException('A user for this action could not be found');
throw new NotFoundException(trans('errors.login_user_not_found'));
}

return $user;
Expand Down
17 changes: 11 additions & 6 deletions app/Access/Controllers/MfaTotpController.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,25 @@ class MfaTotpController extends Controller

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(TotpService $totp)
public function generate()
{
if (session()->has(static::SETUP_SECRET_SESSION_KEY)) {
$totpSecret = decrypt(session()->get(static::SETUP_SECRET_SESSION_KEY));
} else {
$totpSecret = $totp->generateSecret();
$totpSecret = $this->totp->generateSecret();
session()->put(static::SETUP_SECRET_SESSION_KEY, encrypt($totpSecret));
}

$qrCodeUrl = $totp->generateUrl($totpSecret, $this->currentOrLastAttemptedUser());
$svg = $totp->generateQrCodeSvg($qrCodeUrl);
$qrCodeUrl = $this->totp->generateUrl($totpSecret, $this->currentOrLastAttemptedUser());
$svg = $this->totp->generateQrCodeSvg($qrCodeUrl);

$this->setPageTitle(trans('auth.mfa_gen_totp_title'));

Expand All @@ -56,7 +61,7 @@ public function confirm(Request $request)
'code' => [
'required',
'max:12', 'min:4',
new TotpValidationRule($totpSecret),
new TotpValidationRule($totpSecret, $this->totp),
],
]);

Expand Down Expand Up @@ -87,7 +92,7 @@ public function verify(Request $request, LoginService $loginService, MfaSession
'code' => [
'required',
'max:12', 'min:4',
new TotpValidationRule($totpSecret),
new TotpValidationRule($totpSecret, $this->totp),
],
]);

Expand Down
19 changes: 5 additions & 14 deletions app/Access/Controllers/RegisterController.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,13 @@

class RegisterController extends Controller
{
protected SocialDriverManager $socialDriverManager;
protected RegistrationService $registrationService;
protected LoginService $loginService;

/**
* Create a new controller instance.
*/
public function __construct(
SocialDriverManager $socialDriverManager,
RegistrationService $registrationService,
LoginService $loginService
protected SocialDriverManager $socialDriverManager,
protected RegistrationService $registrationService,
protected LoginService $loginService
) {
$this->middleware('guest');
$this->middleware('guard:standard');

$this->socialDriverManager = $socialDriverManager;
$this->registrationService = $registrationService;
$this->loginService = $loginService;
}

/**
Expand Down Expand Up @@ -87,6 +76,8 @@ protected function validator(array $data): ValidatorContract
'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'],
]);
}
}
9 changes: 3 additions & 6 deletions app/Access/Controllers/ResetPasswordController.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,11 @@

class ResetPasswordController extends Controller
{
protected LoginService $loginService;

public function __construct(LoginService $loginService)
{
public function __construct(
protected LoginService $loginService
) {
$this->middleware('guest');
$this->middleware('guard:standard');

$this->loginService = $loginService;
}

/**
Expand Down
2 changes: 1 addition & 1 deletion app/Access/EmailConfirmationService.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class EmailConfirmationService extends UserTokenService
*
* @throws ConfirmationEmailException
*/
public function sendConfirmation(User $user)
public function sendConfirmation(User $user): void
{
if ($user->email_confirmed) {
throw new ConfirmationEmailException(trans('errors.email_already_confirmed'), '/login');
Expand Down
Loading

0 comments on commit 8251df4

Please sign in to comment.