mirror of
https://github.com/BookStackApp/BookStack.git
synced 2024-10-01 01:36:00 -04:00
Compare commits
4 Commits
250aaf652b
...
ade3c24e71
Author | SHA1 | Date | |
---|---|---|---|
|
ade3c24e71 | ||
|
f583354748 | ||
|
d12e8ec923 | ||
|
89f84c9a95 |
10
app/Access/UserInviteException.php
Normal file
10
app/Access/UserInviteException.php
Normal file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace BookStack\Access;
|
||||
|
||||
use Exception;
|
||||
|
||||
class UserInviteException extends Exception
|
||||
{
|
||||
//
|
||||
}
|
@ -13,11 +13,17 @@ class UserInviteService extends UserTokenService
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,6 @@ use BookStack\Entities\Models\PageRevision;
|
||||
use BookStack\Entities\Queries\EntityQueries;
|
||||
use BookStack\Entities\Tools\BookContents;
|
||||
use BookStack\Entities\Tools\PageContent;
|
||||
use BookStack\Entities\Tools\PageEditorData;
|
||||
use BookStack\Entities\Tools\PageEditorType;
|
||||
use BookStack\Entities\Tools\TrashCan;
|
||||
use BookStack\Exceptions\MoveOperationException;
|
||||
@ -44,6 +43,7 @@ class PageRepo
|
||||
'owned_by' => user()->id,
|
||||
'updated_by' => user()->id,
|
||||
'draft' => true,
|
||||
'editor' => PageEditorType::getSystemDefault()->value,
|
||||
]);
|
||||
|
||||
if ($parent instanceof Chapter) {
|
||||
@ -146,8 +146,10 @@ class PageRepo
|
||||
$pageContent->setNewHTML($input['html'], user());
|
||||
}
|
||||
|
||||
if ($newEditor !== $currentEditor && userCan('editor-change')) {
|
||||
if (($newEditor !== $currentEditor || empty($page->editor)) && userCan('editor-change')) {
|
||||
$page->editor = $newEditor->value;
|
||||
} elseif (empty($page->editor)) {
|
||||
$page->editor = $defaultEditor->value;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
namespace BookStack\Users\Controllers;
|
||||
|
||||
use BookStack\Access\SocialDriverManager;
|
||||
use BookStack\Access\UserInviteException;
|
||||
use BookStack\Exceptions\ImageUploadException;
|
||||
use BookStack\Exceptions\UserUpdateException;
|
||||
use BookStack\Http\Controller;
|
||||
@ -14,6 +15,7 @@ use BookStack\Util\SimpleListOptions;
|
||||
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;
|
||||
|
||||
@ -91,9 +93,15 @@ class UserController extends Controller
|
||||
|
||||
$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);
|
||||
});
|
||||
} 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');
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
namespace BookStack\Users;
|
||||
|
||||
use BookStack\Access\UserInviteException;
|
||||
use BookStack\Access\UserInviteService;
|
||||
use BookStack\Activity\ActivityType;
|
||||
use BookStack\Entities\EntityProvider;
|
||||
@ -83,6 +84,7 @@ class UserRepo
|
||||
* 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
|
||||
{
|
||||
|
@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
// Ensure we have an "editor" value set for pages
|
||||
|
||||
// Get default
|
||||
$default = DB::table('settings')
|
||||
->where('setting_key', '=', 'app-editor')
|
||||
->first()
|
||||
->value ?? 'wysiwyg';
|
||||
$default = ($default === 'markdown') ? 'markdown' : 'wysiwyg';
|
||||
|
||||
// We set it to 'markdown' for pages currently with markdown content
|
||||
DB::table('pages')
|
||||
->where('editor', '=', '')
|
||||
->where('markdown', '!=', '')
|
||||
->update(['editor' => 'markdown']);
|
||||
|
||||
// We set it to 'wysiwyg' where we have HTML but no markdown
|
||||
DB::table('pages')
|
||||
->where('editor', '=', '')
|
||||
->where('markdown', '=', '')
|
||||
->where('html', '!=', '')
|
||||
->update(['editor' => 'wysiwyg']);
|
||||
|
||||
// Otherwise, where still empty, set to the current default
|
||||
DB::table('pages')
|
||||
->where('editor', '=', '')
|
||||
->update(['editor' => $default]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
// Can't reverse due to not knowing what would have been empty before
|
||||
}
|
||||
};
|
@ -78,6 +78,7 @@ return [
|
||||
// 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',
|
||||
|
@ -24,6 +24,21 @@ class PageEditorTest extends TestCase
|
||||
$this->withHtml($this->followRedirects($resp))->assertElementExists('#html-editor');
|
||||
}
|
||||
|
||||
public function test_editor_set_for_new_pages()
|
||||
{
|
||||
$book = $this->page->book;
|
||||
|
||||
$this->asEditor()->get($book->getUrl('/create-page'));
|
||||
$newPage = $book->pages()->orderBy('id', 'desc')->first();
|
||||
$this->assertEquals('wysiwyg', $newPage->editor);
|
||||
|
||||
$this->setSettings(['app-editor' => PageEditorType::Markdown->value]);
|
||||
|
||||
$this->asEditor()->get($book->getUrl('/create-page'));
|
||||
$newPage = $book->pages()->orderBy('id', 'desc')->first();
|
||||
$this->assertEquals('markdown', $newPage->editor);
|
||||
}
|
||||
|
||||
public function test_markdown_setting_shows_markdown_editor_for_new_pages()
|
||||
{
|
||||
$this->setSettings(['app-editor' => PageEditorType::Markdown->value]);
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
namespace Tests\User;
|
||||
|
||||
use BookStack\Access\UserInviteException;
|
||||
use BookStack\Access\UserInviteService;
|
||||
use BookStack\Activity\ActivityType;
|
||||
use BookStack\Uploads\Image;
|
||||
@ -229,7 +230,7 @@ class UserManagementTest extends TestCase
|
||||
|
||||
// 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', [
|
||||
@ -247,22 +248,42 @@ class UserManagementTest extends TestCase
|
||||
{
|
||||
/** @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();
|
||||
|
Loading…
Reference in New Issue
Block a user