From 6eadf3efb3c460cc450b0c8b67220a5d00125ff7 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Mon, 31 Jan 2022 22:15:21 +0000 Subject: [PATCH] Added language select to the user create form - Updated user invite to take language from user. - Added tests to cover. - Added page/tab title to user create view. For #2576 and #2408 --- app/Http/Controllers/UserController.php | 11 ++++++- app/Notifications/UserInvite.php | 22 ++++++------- resources/views/users/create.blade.php | 1 + resources/views/users/edit.blade.php | 17 +--------- .../users/parts/language-option-row.blade.php | 18 +++++++++++ tests/Auth/UserInviteTest.php | 32 +++++++++++++++++-- tests/User/UserManagementTest.php | 10 ++++++ 7 files changed, 79 insertions(+), 32 deletions(-) create mode 100644 resources/views/users/parts/language-option-row.blade.php diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php index a76105fa6..eebd4cd4f 100644 --- a/app/Http/Controllers/UserController.php +++ b/app/Http/Controllers/UserController.php @@ -62,6 +62,7 @@ class UserController extends Controller $this->checkPermission('users-manage'); $authMethod = config('auth.method'); $roles = $this->userRepo->getAllRoles(); + $this->setPageTitle(trans('settings.users_add_new')); return view('users.create', ['authMethod' => $authMethod, 'roles' => $roles]); } @@ -78,6 +79,7 @@ class UserController extends Controller $validationRules = [ 'name' => ['required'], 'email' => ['required', 'email', 'unique:users,email'], + 'setting' => ['array'], ]; $authMethod = config('auth.method'); @@ -104,6 +106,13 @@ class UserController extends Controller DB::transaction(function () use ($user, $sendInvite, $request) { $user->save(); + // Save user-specific settings + if ($request->filled('setting')) { + foreach ($request->get('setting') as $key => $value) { + setting()->putUser($user, $key, $value); + } + } + if ($sendInvite) { $this->inviteService->sendInvitation($user); } @@ -198,7 +207,7 @@ class UserController extends Controller $user->external_auth_id = $request->get('external_auth_id'); } - // Save an user-specific settings + // Save user-specific settings if ($request->filled('setting')) { foreach ($request->get('setting') as $key => $value) { setting()->putUser($user, $key, $value); diff --git a/app/Notifications/UserInvite.php b/app/Notifications/UserInvite.php index b0dc9afac..3bae32721 100644 --- a/app/Notifications/UserInvite.php +++ b/app/Notifications/UserInvite.php @@ -2,35 +2,33 @@ namespace BookStack\Notifications; +use BookStack\Auth\User; +use Illuminate\Notifications\Messages\MailMessage; + class UserInvite extends MailNotification { public $token; /** * Create a new notification instance. - * - * @param string $token */ - public function __construct($token) + public function __construct(string $token) { $this->token = $token; } /** * Get the mail representation of the notification. - * - * @param mixed $notifiable - * - * @return \Illuminate\Notifications\Messages\MailMessage */ - public function toMail($notifiable) + public function toMail(User $notifiable): MailMessage { $appName = ['appName' => setting('app-name')]; + $language = setting()->getUser($notifiable, 'language'); return $this->newMailMessage() - ->subject(trans('auth.user_invite_email_subject', $appName)) - ->greeting(trans('auth.user_invite_email_greeting', $appName)) - ->line(trans('auth.user_invite_email_text')) - ->action(trans('auth.user_invite_email_action'), url('/register/invite/' . $this->token)); + ->subject(trans('auth.user_invite_email_subject', $appName, $language)) + ->greeting(trans('auth.user_invite_email_greeting', $appName, $language)) + ->line(trans('auth.user_invite_email_text', [], $language)) + ->action(trans('auth.user_invite_email_action', [], $language), url('/register/invite/' . $this->token)); } } diff --git a/resources/views/users/create.blade.php b/resources/views/users/create.blade.php index 960e38f7c..7015b162a 100644 --- a/resources/views/users/create.blade.php +++ b/resources/views/users/create.blade.php @@ -16,6 +16,7 @@
@include('users.parts.form') + @include('users.parts.language-option-row', ['value' => old('setting.language') ?? config('app.default_locale')])
diff --git a/resources/views/users/edit.blade.php b/resources/views/users/edit.blade.php index 997fd1bf0..41e64dbb9 100644 --- a/resources/views/users/edit.blade.php +++ b/resources/views/users/edit.blade.php @@ -35,22 +35,7 @@
-
-
- -

- {{ trans('settings.users_preferred_language_desc') }} -

-
-
- -
-
- + @include('users.parts.language-option-row', ['value' => setting()->getUser($user, 'language', config('app.default_locale'))])
diff --git a/resources/views/users/parts/language-option-row.blade.php b/resources/views/users/parts/language-option-row.blade.php new file mode 100644 index 000000000..82907b53d --- /dev/null +++ b/resources/views/users/parts/language-option-row.blade.php @@ -0,0 +1,18 @@ +{{-- +$value - Currently selected lanuage value +--}} +
+
+ +

+ {{ trans('settings.users_preferred_language_desc') }} +

+
+
+ +
+
\ No newline at end of file diff --git a/tests/Auth/UserInviteTest.php b/tests/Auth/UserInviteTest.php index 1e1235f33..5b9b14e60 100644 --- a/tests/Auth/UserInviteTest.php +++ b/tests/Auth/UserInviteTest.php @@ -6,6 +6,7 @@ use BookStack\Auth\Access\UserInviteService; use BookStack\Auth\User; use BookStack\Notifications\UserInvite; use Carbon\Carbon; +use Illuminate\Notifications\Messages\MailMessage; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Notification; use Illuminate\Support\Str; @@ -20,8 +21,8 @@ class UserInviteTest extends TestCase $email = Str::random(16) . '@example.com'; $resp = $this->actingAs($admin)->post('/settings/users/create', [ - 'name' => 'Barry', - 'email' => $email, + 'name' => 'Barry', + 'email' => $email, 'send_invite' => 'true', ]); $resp->assertRedirect('/settings/users'); @@ -34,6 +35,31 @@ class UserInviteTest extends TestCase ]); } + public function test_user_invite_sent_in_selected_language() + { + Notification::fake(); + $admin = $this->getAdmin(); + + $email = Str::random(16) . '@example.com'; + $resp = $this->actingAs($admin)->post('/settings/users/create', [ + 'name' => 'Barry', + 'email' => $email, + 'send_invite' => 'true', + 'setting' => [ + 'language' => 'de', + ] + ]); + $resp->assertRedirect('/settings/users'); + + $newUser = User::query()->where('email', '=', $email)->orderBy('id', 'desc')->first(); + Notification::assertSentTo($newUser, UserInvite::class, function ($notification, $channels, $notifiable) { + /** @var MailMessage $mail */ + $mail = $notification->toMail($notifiable); + return 'Du wurdest eingeladen BookStack beizutreten!' === $mail->subject && + 'Ein Konto wurde für Sie auf BookStack erstellt.' === $mail->greeting; + }); + } + public function test_invite_set_password() { Notification::fake(); @@ -54,7 +80,7 @@ class UserInviteTest extends TestCase ]); $setPasswordResp->assertSee('Password set, you should now be able to login using your set password to access BookStack!'); $newPasswordValid = auth()->validate([ - 'email' => $user->email, + 'email' => $user->email, 'password' => 'my test password', ]); $this->assertTrue($newPasswordValid); diff --git a/tests/User/UserManagementTest.php b/tests/User/UserManagementTest.php index 806e35ad4..2fbbee7e2 100644 --- a/tests/User/UserManagementTest.php +++ b/tests/User/UserManagementTest.php @@ -183,6 +183,16 @@ class UserManagementTest extends TestCase $resp->assertSee('cannot delete the guest user'); } + public function test_user_create_language_reflects_default_system_locale() + { + $langs = ['en', 'fr', 'hr']; + foreach ($langs as $lang) { + config()->set('app.locale', $lang); + $resp = $this->asAdmin()->get('/settings/users/create'); + $resp->assertElementExists('select[name="setting[language]"] option[value="' . $lang . '"][selected]'); + } + } + public function test_user_creation_is_not_performed_if_the_invitation_sending_fails() { /** @var User $user */