mirror of
https://github.com/Bubka/2FAuth.git
synced 2024-12-26 00:50:12 +01:00
Add a test email feature to the admin panel - Closes #307
This commit is contained in:
parent
04078b09aa
commit
88d37394d3
@ -3,10 +3,12 @@
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Facades\Settings;
|
||||
use App\Notifications\TestEmailSettingNotification;
|
||||
use App\Services\ReleaseRadarService;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class SystemController extends Controller
|
||||
{
|
||||
@ -58,4 +60,20 @@ public function latestRelease(Request $request, ReleaseRadarService $releaseRada
|
||||
|
||||
return response()->json(['newRelease' => $release]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a test email.
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function testEmail(Request $request)
|
||||
{
|
||||
try {
|
||||
$request->user()->notify(new TestEmailSettingNotification());
|
||||
} catch (\Throwable $th) {
|
||||
Log::error($th->getMessage());
|
||||
}
|
||||
|
||||
return response()->json(['message' => 'Ok']);
|
||||
}
|
||||
}
|
||||
|
64
app/Notifications/TestEmailSettingNotification.php
Normal file
64
app/Notifications/TestEmailSettingNotification.php
Normal file
@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
namespace App\Notifications;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
use Illuminate\Notifications\Notification;
|
||||
use Illuminate\Support\Facades\Lang;
|
||||
|
||||
class TestEmailSettingNotification extends Notification
|
||||
{
|
||||
|
||||
// /**
|
||||
// * The callback that should be used to create the reset password URL.
|
||||
// *
|
||||
// * @var \Closure|null
|
||||
// */
|
||||
// protected static ?Closure $createUrlCallback;
|
||||
|
||||
// /**
|
||||
// * The callback that should be used to build the mail message.
|
||||
// *
|
||||
// * @var \Closure|null
|
||||
// */
|
||||
// protected static ?Closure $toMailCallback;
|
||||
|
||||
/**
|
||||
* TestEmailSettingNotification constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the notification's delivery channels.
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
* @return array
|
||||
*/
|
||||
public function via($notifiable)
|
||||
{
|
||||
return ['mail'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the mail representation of the notification.
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
* @return \Illuminate\Notifications\Messages\MailMessage
|
||||
*/
|
||||
public function toMail($notifiable)
|
||||
{
|
||||
return (new MailMessage)
|
||||
->subject(Lang::get('notifications.test_email_settings.subject'))
|
||||
->greeting(Lang::get('notifications.hello'))
|
||||
->line(
|
||||
Lang::get('notifications.test_email_settings.reason')
|
||||
)
|
||||
->line(
|
||||
Lang::get('notifications.test_email_settings.success')
|
||||
);
|
||||
}
|
||||
}
|
4
resources/js/icons.js
vendored
4
resources/js/icons.js
vendored
@ -49,7 +49,8 @@ import {
|
||||
} from '@fortawesome/free-solid-svg-icons'
|
||||
|
||||
import {
|
||||
faStar
|
||||
faStar,
|
||||
faPaperPlane,
|
||||
} from '@fortawesome/free-regular-svg-icons'
|
||||
|
||||
import {
|
||||
@ -105,6 +106,7 @@ library.add(
|
||||
faStar,
|
||||
faChevronRight,
|
||||
faOpenid,
|
||||
faPaperPlane,
|
||||
);
|
||||
|
||||
export default FontAwesomeIcon
|
8
resources/js/services/systemService.js
vendored
8
resources/js/services/systemService.js
vendored
@ -17,6 +17,14 @@ export default {
|
||||
*/
|
||||
getLastRelease(config = {}) {
|
||||
return webClient.get('latestRelease', { ...config })
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* @returns Promise
|
||||
*/
|
||||
sendTestEmail(config = {}) {
|
||||
return webClient.post('testEmail', { ...config })
|
||||
}
|
||||
|
||||
}
|
@ -4,16 +4,19 @@
|
||||
import systemService from '@/services/systemService'
|
||||
import { useAppSettingsStore } from '@/stores/appSettings'
|
||||
import { useNotifyStore } from '@/stores/notify'
|
||||
import { useUserStore } from '@/stores/user'
|
||||
import VersionChecker from '@/components/VersionChecker.vue'
|
||||
import CopyButton from '@/components/CopyButton.vue'
|
||||
|
||||
const $2fauth = inject('2fauth')
|
||||
const user = useUserStore()
|
||||
const notify = useNotifyStore()
|
||||
const appSettings = useAppSettingsStore()
|
||||
const returnTo = useStorage($2fauth.prefix + 'returnTo', 'accounts')
|
||||
|
||||
const infos = ref()
|
||||
const listInfos = ref(null)
|
||||
const isSendingTestEmail = ref(false)
|
||||
|
||||
/**
|
||||
* Saves a setting on the backend
|
||||
@ -26,6 +29,18 @@
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a test email
|
||||
*/
|
||||
function sendTestEmail() {
|
||||
isSendingTestEmail.value = true;
|
||||
|
||||
systemService.sendTestEmail()
|
||||
.finally(() => {
|
||||
isSendingTestEmail.value = false;
|
||||
})
|
||||
}
|
||||
|
||||
onBeforeRouteLeave((to) => {
|
||||
if (! to.name.startsWith('admin.')) {
|
||||
notify.clear()
|
||||
@ -53,6 +68,22 @@
|
||||
<!-- Check for update -->
|
||||
<FormCheckbox v-model="appSettings.checkForUpdate" @update:model-value="val => saveSetting('checkForUpdate', val)" fieldName="checkForUpdate" label="commons.check_for_update" help="commons.check_for_update_help" />
|
||||
<VersionChecker />
|
||||
<div class="field">
|
||||
<!-- <h5 class="title is-5">{{ $t('settings.security') }}</h5> -->
|
||||
<label class="label" v-html="$t('admin.forms.test_email.label')" />
|
||||
<p class="help" v-html="$t('admin.forms.test_email.help')" />
|
||||
<p class="help" v-html="$t('admin.forms.test_email.email_will_be_send_to_x', { email: user.email })" />
|
||||
</div>
|
||||
<div class="columns is-mobile is-vcentered">
|
||||
<div class="column is-narrow">
|
||||
<button type="button" :class="isSendingTestEmail ? 'is-loading' : ''" class="button is-link is-rounded is-small" @click="sendTestEmail">
|
||||
<span class="icon is-small">
|
||||
<FontAwesomeIcon :icon="['far', 'paper-plane']" />
|
||||
</span>
|
||||
<span>{{ $t('commons.send') }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<h4 class="title is-4 pt-4 has-text-grey-light">{{ $t('settings.security') }}</h4>
|
||||
<!-- protect db -->
|
||||
<FormCheckbox v-model="appSettings.useEncryption" @update:model-value="val => saveSetting('useEncryption', val)" fieldName="useEncryption" label="admin.forms.use_encryption.label" help="admin.forms.use_encryption.help" />
|
||||
|
@ -79,6 +79,11 @@
|
||||
'is_admin' => [
|
||||
'label' => 'Is administrator',
|
||||
'help' => 'Give administrator rights to the user. Administrators have permissions to manage the whole app, i.e. settings and other users, but cannot generate password for a 2FA they don\'t own.'
|
||||
],
|
||||
'test_email' => [
|
||||
'label' => 'Email configuration test',
|
||||
'help' => 'Send a test email to control your instance\'s email configuration. It is important to have a working configuration, otherwise users will not be able to request a reset password.',
|
||||
'email_will_be_send_to_x' => 'The email will be send to <span class="is-family-code has-text-info">:email</span>',
|
||||
]
|
||||
],
|
||||
|
||||
|
@ -79,5 +79,6 @@
|
||||
'nothing' => 'nothing',
|
||||
'no_result' => 'No result',
|
||||
'information' => 'Information',
|
||||
'permissions' => 'Permissions'
|
||||
'permissions' => 'Permissions',
|
||||
'send' => 'Send',
|
||||
];
|
||||
|
23
resources/lang/en/notifications.php
Normal file
23
resources/lang/en/notifications.php
Normal file
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Notifications Language Lines
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The following language lines are used during authentication for various
|
||||
| messages that we need to display to the user. You are free to modify
|
||||
| these language lines according to your application's requirements.
|
||||
|
|
||||
*/
|
||||
|
||||
'hello' => 'Hello',
|
||||
'test_email_settings' => [
|
||||
'subject' => '2FAuth test email',
|
||||
'reason' => 'You are receiving this email because you requested a test email to validate the email settings of your 2FAuth instance.',
|
||||
'success' => 'Good news, it works :)'
|
||||
],
|
||||
|
||||
];
|
@ -83,6 +83,7 @@
|
||||
*/
|
||||
Route::group(['middleware' => ['behind-auth', 'admin']], function () {
|
||||
Route::get('infos', [SystemController::class, 'infos'])->name('system.infos');
|
||||
Route::post('testEmail', [SystemController::class, 'testEmail'])->name('system.testEmail');
|
||||
});
|
||||
|
||||
Route::get('latestRelease', [SystemController::class, 'latestRelease'])->name('system.latestRelease');
|
||||
|
@ -4,8 +4,9 @@
|
||||
|
||||
use App\Http\Controllers\SystemController;
|
||||
use App\Models\User;
|
||||
use App\Notifications\TestEmailSettingNotification;
|
||||
use App\Services\ReleaseRadarService;
|
||||
use Illuminate\Foundation\Testing\WithoutMiddleware;
|
||||
use Illuminate\Support\Facades\Notification;
|
||||
use PHPUnit\Framework\Attributes\CoversClass;
|
||||
use Tests\FeatureTestCase;
|
||||
|
||||
@ -15,8 +16,6 @@
|
||||
#[CoversClass(SystemController::class)]
|
||||
class SystemControllerTest extends FeatureTestCase
|
||||
{
|
||||
//use WithoutMiddleware;
|
||||
|
||||
/**
|
||||
* @var \App\Models\User|\Illuminate\Contracts\Auth\Authenticatable
|
||||
*/
|
||||
@ -116,4 +115,38 @@ public function test_latestrelease_runs_manual_scan()
|
||||
'newRelease' => 'new_release',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function test_testEmail_sends_a_notification()
|
||||
{
|
||||
Notification::fake();
|
||||
|
||||
$response = $this->actingAs($this->admin, 'web-guard')
|
||||
->json('POST', '/testEmail', []);
|
||||
|
||||
$response->assertStatus(200);
|
||||
|
||||
Notification::assertSentTo($this->admin, TestEmailSettingNotification::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function test_testEmail_returns_unauthorized()
|
||||
{
|
||||
$response = $this->json('GET', '/infos')
|
||||
->assertUnauthorized();
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function test_testEmail_returns_forbidden()
|
||||
{
|
||||
$response = $this->actingAs($this->user, 'api-guard')
|
||||
->json('GET', '/infos')
|
||||
->assertForbidden();
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user