--- /dev/null
+<?php
+
+namespace BookStack\Access;
+
+use Exception;
+
+class UserInviteException extends Exception
+{
+ //
+}
/**
* Send an invitation to a user to sign into BookStack
* Removes existing invitation tokens.
+ * @throws UserInviteException
*/
public function sendInvitation(User $user)
{
$this->deleteByUser($user);
$token = $this->createTokenForUser($user);
- $user->notify(new UserInviteNotification($token));
+
+ try {
+ $user->notify(new UserInviteNotification($token));
+ } catch (\Exception $exception) {
+ throw new UserInviteException($exception->getMessage(), $exception->getCode(), $exception);
+ }
}
}
namespace BookStack\Users\Controllers;
use BookStack\Access\SocialDriverManager;
+use BookStack\Access\UserInviteException;
use BookStack\Exceptions\ImageUploadException;
use BookStack\Exceptions\UserUpdateException;
use BookStack\Http\Controller;
use Exception;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
+use Illuminate\Support\Facades\Log;
use Illuminate\Validation\Rules\Password;
use Illuminate\Validation\ValidationException;
$validated = $this->validate($request, array_filter($validationRules));
- DB::transaction(function () use ($validated, $sendInvite) {
- $this->userRepo->create($validated, $sendInvite);
- });
+ try {
+ DB::transaction(function () use ($validated, $sendInvite) {
+ $this->userRepo->create($validated, $sendInvite);
+ dd('post-create');
+ });
+ } catch (UserInviteException $e) {
+ Log::error("Failed to send user invite with error: {$e->getMessage()}");
+ $this->showErrorNotification(trans('errors.users_could_not_send_invite'));
+ return redirect('/settings/users/create')->withInput();
+ }
return redirect('/settings/users');
}
namespace BookStack\Users;
+use BookStack\Access\UserInviteException;
use BookStack\Access\UserInviteService;
use BookStack\Activity\ActivityType;
use BookStack\Entities\EntityProvider;
* As per "createWithoutActivity" but records a "create" activity.
*
* @param array{name: string, email: string, password: ?string, external_auth_id: ?string, language: ?string, roles: ?array} $data
+ * @throws UserInviteException
*/
public function create(array $data, bool $sendInvite = false): User
{
// Users
'users_cannot_delete_only_admin' => 'You cannot delete the only admin',
'users_cannot_delete_guest' => 'You cannot delete the guest user',
+ 'users_could_not_send_invite' => 'Could not create user since invite email failed to send',
// Roles
'role_cannot_be_edited' => 'This role cannot be edited',
namespace Tests\User;
+use BookStack\Access\UserInviteException;
use BookStack\Access\UserInviteService;
use BookStack\Activity\ActivityType;
use BookStack\Uploads\Image;
// Simulate an invitation sending failure
$this->mock(UserInviteService::class, function (MockInterface $mock) {
- $mock->shouldReceive('sendInvitation')->once()->andThrow(RuntimeException::class);
+ $mock->shouldReceive('sendInvitation')->once()->andThrow(UserInviteException::class);
});
$this->asAdmin()->post('/settings/users/create', [
{
/** @var User $user */
$user = User::factory()->make();
- $adminRole = Role::getRole('admin');
$this->mock(UserInviteService::class, function (MockInterface $mock) {
- $mock->shouldReceive('sendInvitation')->once()->andThrow(RuntimeException::class);
+ $mock->shouldReceive('sendInvitation')->once()->andThrow(UserInviteException::class);
});
$this->asAdmin()->post('/settings/users/create', [
'name' => $user->name,
'email' => $user->email,
'send_invite' => 'true',
- 'roles[' . $adminRole->id . ']' => 'true',
]);
$this->assertDatabaseMissing('activities', ['type' => 'USER_CREATE']);
}
+ public function test_return_to_form_with_warning_if_the_invitation_sending_fails()
+ {
+ $logger = $this->withTestLogger();
+ /** @var User $user */
+ $user = User::factory()->make();
+
+ $this->mock(UserInviteService::class, function (MockInterface $mock) {
+ $mock->shouldReceive('sendInvitation')->once()->andThrow(UserInviteException::class);
+ });
+
+ $resp = $this->asAdmin()->post('/settings/users/create', [
+ 'name' => $user->name,
+ 'email' => $user->email,
+ 'send_invite' => 'true',
+ ]);
+
+ $resp->assertRedirect('/settings/users/create');
+ $this->assertSessionError('Could not create user since invite email failed to send');
+ $this->assertEquals($user->email, session()->getOldInput('email'));
+ $this->assertTrue($logger->hasErrorThatContains('Failed to send user invite with error:'));
+ }
+
public function test_user_create_update_fails_if_locale_is_invalid()
{
$user = $this->users->editor();