Added MFA indicator to user list

Also fixed issue with showing incorrect MFA method count on user edit
page changes done in last commit
This commit is contained in:
Dan Brown 2021-07-14 20:18:48 +01:00
parent bb43acef21
commit cfc0c593db
No known key found for this signature in database
GPG Key ID: 46D9F943C24A2EF9
5 changed files with 31 additions and 9 deletions

View File

@ -39,6 +39,7 @@ use Illuminate\Support\Collection;
* @property string $external_auth_id * @property string $external_auth_id
* @property string $system_name * @property string $system_name
* @property Collection $roles * @property Collection $roles
* @property Collection $mfaValues
*/ */
class User extends Model implements AuthenticatableContract, CanResetPasswordContract, Loggable, Sluggable class User extends Model implements AuthenticatableContract, CanResetPasswordContract, Loggable, Sluggable
{ {

View File

@ -71,6 +71,7 @@ class UserRepo
$query = User::query()->select(['*']) $query = User::query()->select(['*'])
->withLastActivityAt() ->withLastActivityAt()
->with(['roles', 'avatar']) ->with(['roles', 'avatar'])
->withCount('mfaValues')
->orderBy($sort, $sortData['order']); ->orderBy($sort, $sortData['order']);
if ($sortData['search']) { if ($sortData['search']) {

View File

@ -123,12 +123,13 @@ class UserController extends Controller
{ {
$this->checkPermissionOrCurrentUser('users-manage', $id); $this->checkPermissionOrCurrentUser('users-manage', $id);
$user = $this->user->newQuery()->with(['apiTokens'])->findOrFail($id); /** @var User $user */
$user = $this->user->newQuery()->with(['apiTokens', 'mfaValues'])->findOrFail($id);
$authMethod = ($user->system_name) ? 'system' : config('auth.method'); $authMethod = ($user->system_name) ? 'system' : config('auth.method');
$activeSocialDrivers = $socialAuthService->getActiveDrivers(); $activeSocialDrivers = $socialAuthService->getActiveDrivers();
$mfaMethods = user()->mfaValues()->get(['id', 'method'])->groupBy('method'); $mfaMethods = $user->mfaValues->groupBy('method');
$this->setPageTitle(trans('settings.user_profile')); $this->setPageTitle(trans('settings.user_profile'));
$roles = $this->userRepo->getAllRoles(); $roles = $this->userRepo->getAllRoles();

View File

@ -43,7 +43,12 @@
<td class="text-center" style="line-height: 0;"><img class="avatar med" src="{{ $user->getAvatar(40)}}" alt="{{ $user->name }}"></td> <td class="text-center" style="line-height: 0;"><img class="avatar med" src="{{ $user->getAvatar(40)}}" alt="{{ $user->name }}"></td>
<td> <td>
<a href="{{ url("/settings/users/{$user->id}") }}"> <a href="{{ url("/settings/users/{$user->id}") }}">
{{ $user->name }} <br> <span class="text-muted">{{ $user->email }}</span> {{ $user->name }}
<br>
<span class="text-muted">{{ $user->email }}</span>
@if($user->mfa_values_count > 0)
<span title="MFA Configured" class="text-pos">@icon('lock')</span>
@endif
</a> </a>
</td> </td>
<td> <td>

View File

@ -3,6 +3,7 @@
namespace Tests\Auth; namespace Tests\Auth;
use BookStack\Auth\Access\Mfa\MfaValue; use BookStack\Auth\Access\Mfa\MfaValue;
use BookStack\Auth\User;
use PragmaRX\Google2FA\Google2FA; use PragmaRX\Google2FA\Google2FA;
use Tests\TestCase; use Tests\TestCase;
@ -108,16 +109,16 @@ class MfaConfigurationTest extends TestCase
public function test_mfa_method_count_is_visible_on_user_edit_page() public function test_mfa_method_count_is_visible_on_user_edit_page()
{ {
$admin = $this->getAdmin(); $user = $this->getEditor();
$resp = $this->actingAs($admin)->get($admin->getEditUrl()); $resp = $this->actingAs($this->getAdmin())->get($user->getEditUrl());
$resp->assertSee('0 methods configured'); $resp->assertSee('0 methods configured');
MfaValue::upsertWithValue($admin, MfaValue::METHOD_TOTP, 'test'); MfaValue::upsertWithValue($user, MfaValue::METHOD_TOTP, 'test');
$resp = $this->actingAs($admin)->get($admin->getEditUrl()); $resp = $this->get($user->getEditUrl());
$resp->assertSee('1 method configured'); $resp->assertSee('1 method configured');
MfaValue::upsertWithValue($admin, MfaValue::METHOD_BACKUP_CODES, 'test'); MfaValue::upsertWithValue($user, MfaValue::METHOD_BACKUP_CODES, 'test');
$resp = $this->actingAs($admin)->get($admin->getEditUrl()); $resp = $this->get($user->getEditUrl());
$resp->assertSee('2 methods configured'); $resp->assertSee('2 methods configured');
} }
@ -131,4 +132,17 @@ class MfaConfigurationTest extends TestCase
$resp->assertElementNotExists('a[href$="/mfa/setup"]'); $resp->assertElementNotExists('a[href$="/mfa/setup"]');
} }
public function test_mfa_indicator_shows_in_user_list()
{
$admin = $this->getAdmin();
User::query()->where('id', '!=', $admin->id)->delete();
$resp = $this->actingAs($admin)->get('/settings/users');
$resp->assertElementNotExists('[title="MFA Configured"] svg');
MfaValue::upsertWithValue($admin, MfaValue::METHOD_TOTP, 'test');
$resp = $this->actingAs($admin)->get('/settings/users');
$resp->assertElementExists('[title="MFA Configured"] svg');
}
} }