Add a reset command to set up a Testing app with data (like Demo)

This commit is contained in:
Bubka 2022-07-07 16:39:57 +02:00
parent b4240bf1af
commit cb2de26e93
13 changed files with 346 additions and 65 deletions

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,67 @@
<?php
namespace App\Console\Commands;
use App\Console\Commands\Utils\ResetTrait;
use Illuminate\Console\Command;
class ResetTesting extends Command
{
use ResetTrait;
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = '2fauth:reset-testing {--no-confirm}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Reset 2FAuth with a fresh testing content';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
if( !config('2fauth.config.isTestingApp') ) {
$this->comment('2fauth:reset-testing can only run when isTestingApp option is On');
return;
}
if( $this->option('no-confirm') ) {
$testing = 'testing';
}
else {
$this->line('This will reset the app in order to run a clean and fresh testing app.');
$testing = $this->ask('To prevent any mistake please type the word "testing" to go on');
}
if ($testing === 'testing') {
$this->resetIcons();
$this->resetDB('TestingSeeder');
$this->info('Testing app refreshed');
}
else {
$this->comment('Bad confirmation word, nothing appened');
}
}
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,90 @@
<?php
namespace App\Console\Commands\Utils;
use App\Console\Commands\Utils\IconGenerator;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;
trait ResetTrait
{
/**
* Reset icons
*/
protected function resetIcons()
{
$this->deleteIcons();
$this->generateIcons();
}
/**
* Delete all icons
*/
protected function deleteIcons()
{
$filesForDelete = \Illuminate\Support\Facades\File::glob('public/icons/*.png');
Storage::delete($filesForDelete);
$this->line('Existing icons deleted');
}
/**
* Generate icons for seeded accounts
*/
protected function generateIcons()
{
IconGenerator::generateIcon('amazon', IconGenerator::AMAZON);
IconGenerator::generateIcon('apple', IconGenerator::APPLE);
IconGenerator::generateIcon('dropbox', IconGenerator::DROPBOX);
IconGenerator::generateIcon('facebook', IconGenerator::FACEBOOK);
IconGenerator::generateIcon('github', IconGenerator::GITHUB);
IconGenerator::generateIcon('google', IconGenerator::GOOGLE);
IconGenerator::generateIcon('instagram', IconGenerator::INSTAGRAM);
IconGenerator::generateIcon('linkedin', IconGenerator::LINKEDIN);
IconGenerator::generateIcon('twitter', IconGenerator::TWITTER);
$this->line('Icons regenerated');
}
/**
* Reset DB
*/
protected function resetDB(string $seeder)
{
$this->flushDB();
$this->seedDB($seeder);
}
/**
* Delete all DB tables
*/
protected function flushDB()
{
// Reset the db
DB::table('users')->delete();
DB::table('password_resets')->delete();
DB::table('oauth_access_tokens')->delete();
DB::table('oauth_personal_access_clients')->delete();
DB::table('oauth_refresh_tokens')->delete();
DB::table('web_authn_credentials')->delete();
DB::table('web_authn_recoveries')->delete();
DB::table('twofaccounts')->delete();
DB::table('options')->delete();
DB::table('groups')->delete();
$this->line('Database cleaned');
}
/**
* Seed the DB
*/
protected function seedDB(string $seeder)
{
$this->callSilent('db:seed', [
'--class' => $seeder
]);
$this->line('Database seeded');
}
}

View File

@ -38,6 +38,7 @@ public function index()
])->toJson(), ])->toJson(),
'lang' => App::currentLocale(), 'lang' => App::currentLocale(),
'isDemoApp' => config("2fauth.config.isDemoApp") ? 'true' : 'false', 'isDemoApp' => config("2fauth.config.isDemoApp") ? 'true' : 'false',
'isTestingApp' => config("2fauth.config.isTestingApp") ? 'true' : 'false',
'locales' => collect(config("2fauth.locales"))->toJson() 'locales' => collect(config("2fauth.locales"))->toJson()
]); ]);
} }

View File

@ -20,6 +20,7 @@
'config' => [ 'config' => [
'isDemoApp' => env('IS_DEMO_APP', false), 'isDemoApp' => env('IS_DEMO_APP', false),
'isTestingApp' => env('IS_TESTING_APP', false),
'trustedProxies' => env('TRUSTED_PROXIES', null), 'trustedProxies' => env('TRUSTED_PROXIES', null),
'proxyLogoutUrl' => env('PROXY_LOGOUT_URL', null), 'proxyLogoutUrl' => env('PROXY_LOGOUT_URL', null),
], ],

View File

@ -0,0 +1,140 @@
<?php
namespace Database\Seeders;
use App\Models\User;
use App\Models\Group;
use App\Models\TwoFAccount;
use Illuminate\Database\Seeder;
class TestingSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
User::create([
'name' => 'tester',
'email' => 'tester@2fauth.app',
'password' => bcrypt('password'),
]);
$groupSocialNetwork = Group::create([
'name' => 'Social Networks',
]);
$groupSocialNetwork->twofaccounts()->createMany([
[
'otp_type' => 'totp',
'account' => 'johndoe@facebook.com',
'service' => 'Facebook',
'secret' => 'A4GRFTVVRBGY7UIW',
'algorithm' => 'sha1',
'digits' => 6,
'period' => 30,
'icon' => 'facebook.png',
'legacy_uri' => 'otpauth://totp/Facebook:johndoe@facebook.com?secret=A4GRFTVVRBGY7UIW',
],
[
'otp_type' => 'totp',
'service' => 'Twitter',
'account' => '@john',
'secret' => 'A2GRFTVVRBGY7UIW',
'algorithm' => 'sha1',
'digits' => 6,
'period' => 30,
'icon' => 'twitter.png',
'legacy_uri' => 'otpauth://totp/Twitter:@john?secret=A2GRFTVVRBGY7UIW',
],
[
'otp_type' => 'totp',
'service' => 'Instagram',
'account' => '@johndoe',
'secret' => 'A6GRFTVVRBGY7UIW',
'algorithm' => 'sha1',
'digits' => 6,
'period' => 30,
'icon' => 'instagram.png',
'legacy_uri' => 'otpauth://totp/Instagram:@johndoe?secret=A6GRFTVVRBGY7UIW',
],
[
'otp_type' => 'totp',
'service' => 'LinkedIn',
'account' => '@johndoe',
'secret' => 'A7GRFTVVRBGY7UIW',
'algorithm' => 'sha1',
'digits' => 6,
'period' => 30,
'icon' => 'linkedin.png',
'legacy_uri' => 'otpauth://totp/LinkedIn:@johndoe?secret=A7GRFTVVRBGY7UIW',
]
]);
$groupECommerce = Group::create([
'name' => 'eCommerce',
]);
$groupECommerce->twofaccounts()->create([
'otp_type' => 'totp',
'account' => 'johndoe',
'service' => 'Amazon',
'secret' => 'A7GRFTVVRBGY7UIW',
'algorithm' => 'sha1',
'digits' => 6,
'period' => 30,
'icon' => 'amazon.png',
'legacy_uri' => 'otpauth://totp/Amazon:johndoe?secret=A7GRFTVVRBGY7UIW',
]);
TwoFAccount::create([
'otp_type' => 'totp',
'account' => 'john.doe@icloud.com',
'service' => 'Apple',
'secret' => 'A2GRFTVVRBGY7UIW',
'algorithm' => 'sha1',
'digits' => 6,
'period' => 30,
'icon' => 'apple.png',
'legacy_uri' => 'otpauth://totp/Apple:john.doe@icloud.com?secret=A2GRFTVVRBGY7UIW',
]);
TwoFAccount::create([
'otp_type' => 'totp',
'account' => 'john.doe',
'service' => 'Dropbox',
'secret' => 'A3GRFTVVRBGY7UIW',
'algorithm' => 'sha1',
'digits' => 6,
'period' => 30,
'icon' => 'dropbox.png',
'legacy_uri' => 'otpauth://totp/Dropbox:john.doe?secret=A3GRFTVVRBGY7UIW',
]);
TwoFAccount::create([
'otp_type' => 'totp',
'account' => '@john',
'service' => 'Github',
'secret' => 'A2GRFTVVRBGY7UIW',
'algorithm' => 'sha1',
'digits' => 6,
'period' => 30,
'icon' => 'github.png',
'legacy_uri' => 'otpauth://totp/Github:@john?secret=A2GRFTVVRBGY7UIW',
]);
TwoFAccount::create([
'otp_type' => 'totp',
'service' => 'Google',
'account' => 'john.doe@gmail.com',
'secret' => 'A5GRFTVVRBGY7UIW',
'algorithm' => 'sha1',
'digits' => 6,
'period' => 30,
'icon' => 'google.png',
'legacy_uri' => 'otpauth://totp/Google:john.doe@gmail.com?secret=A5GRFTVVRBGY7UIW',
]);
}
}

3
resources/js/app.js vendored
View File

@ -17,7 +17,8 @@ const app = new Vue({
data: { data: {
appSettings: window.appSettings, appSettings: window.appSettings,
appConfig: window.appConfig, appConfig: window.appConfig,
isDemoApp: window.isDemoApp isDemoApp: window.isDemoApp,
isTestingApp: window.isTestingApp
}, },
i18n, i18n,
router, router,

View File

@ -4,6 +4,9 @@
<div v-if="this.$root.isDemoApp" class="demo has-background-warning has-text-centered is-size-7-mobile"> <div v-if="this.$root.isDemoApp" class="demo has-background-warning has-text-centered is-size-7-mobile">
{{ $t('commons.demo_do_not_post_sensitive_data') }} {{ $t('commons.demo_do_not_post_sensitive_data') }}
</div> </div>
<div v-if="this.$root.isTestingApp" class="demo has-background-warning has-text-centered is-size-7-mobile">
{{ $t('commons.testing_do_not_post_sensitive_data') }}
</div>
<notifications width="100%" position="top" :duration="4000" :speed="0" :max="1" classes="notification is-radiusless" /> <notifications width="100%" position="top" :duration="4000" :speed="0" :max="1" classes="notification is-radiusless" />
<main class="main-section"> <main class="main-section">
<router-view></router-view> <router-view></router-view>

View File

@ -16,6 +16,7 @@
<!-- login/password legacy form --> <!-- login/password legacy form -->
<form-wrapper v-else :title="$t('auth.forms.login')" :punchline="punchline"> <form-wrapper v-else :title="$t('auth.forms.login')" :punchline="punchline">
<div v-if="isDemo" class="notification is-info has-text-centered is-radiusless" v-html="$t('auth.forms.welcome_to_demo_app_use_those_credentials')" /> <div v-if="isDemo" class="notification is-info has-text-centered is-radiusless" v-html="$t('auth.forms.welcome_to_demo_app_use_those_credentials')" />
<div v-if="isTesting" class="notification is-warning has-text-centered is-radiusless" v-html="$t('auth.forms.welcome_to_testing_app_use_those_credentials')" />
<form @submit.prevent="handleSubmit" @keydown="form.onKeydown($event)"> <form @submit.prevent="handleSubmit" @keydown="form.onKeydown($event)">
<form-field :form="form" fieldName="email" inputType="email" :label="$t('auth.forms.email')" autofocus /> <form-field :form="form" fieldName="email" inputType="email" :label="$t('auth.forms.email')" autofocus />
<form-field :form="form" fieldName="password" inputType="password" :label="$t('auth.forms.password')" /> <form-field :form="form" fieldName="password" inputType="password" :label="$t('auth.forms.password')" />
@ -43,6 +44,7 @@
return { return {
username: null, username: null,
isDemo: this.$root.isDemoApp, isDemo: this.$root.isDemoApp,
isTesting: this.$root.isTestingApp,
form: new Form({ form: new Form({
email: '', email: '',
password: '' password: ''

View File

@ -95,7 +95,8 @@
'password_successfully_changed' => 'Password successfully changed', 'password_successfully_changed' => 'Password successfully changed',
'edit_account' => 'Edit account', 'edit_account' => 'Edit account',
'profile_saved' => 'Profile successfully updated!', 'profile_saved' => 'Profile successfully updated!',
'welcome_to_demo_app_use_those_credentials' => 'Welcome to the 2FAuth demo.<br><br>You can connect using the email address <strong>demo@2fauth.app</strong> and the password <strong>demo</demo>', 'welcome_to_demo_app_use_those_credentials' => 'Welcome to the 2FAuth demo.<br><br>You can connect using the email address <strong>demo@2fauth.app</strong> and the password <strong>demo</strong>',
'welcome_to_testing_app_use_those_credentials' => 'Welcome to the 2FAuth testing instance.<br><br>Use email address <strong>testing@2fauth.app</strong> and password <strong>password</strong>',
'register_punchline' => 'Welcome to 2FAuth.<br/>You need an account to go further. Fill this form to register yourself, and please, choose a strong password, 2FA data are sensitives.', 'register_punchline' => 'Welcome to 2FAuth.<br/>You need an account to go further. Fill this form to register yourself, and please, choose a strong password, 2FA data are sensitives.',
'reset_punchline' => '2FAuth will send you a password reset link to this address. Click the link in the received email to set a new password.', 'reset_punchline' => '2FAuth will send you a password reset link to this address. Click the link in the received email to set a new password.',
'name_this_device' => 'Name this device', 'name_this_device' => 'Name this device',

View File

@ -27,6 +27,7 @@
'save' => 'Save', 'save' => 'Save',
'close' => 'Close', 'close' => 'Close',
'demo_do_not_post_sensitive_data' => 'This is a demo app, do not post any sensitive data', 'demo_do_not_post_sensitive_data' => 'This is a demo app, do not post any sensitive data',
'testing_do_not_post_sensitive_data' => 'This is a testing app, do not post any sensitive data',
'selected' => 'selected', 'selected' => 'selected',
'name' => 'Name', 'name' => 'Name',
'manage' => 'Manage', 'manage' => 'Manage',

View File

@ -27,6 +27,7 @@
var appConfig = {!! $appConfig !!}; var appConfig = {!! $appConfig !!};
var appVersion = '{{ config("2fauth.version") }}'; var appVersion = '{{ config("2fauth.version") }}';
var isDemoApp = {!! $isDemoApp !!}; var isDemoApp = {!! $isDemoApp !!};
var isTestingApp = {!! $isTestingApp !!};
var appLocales = {!! $locales !!}; var appLocales = {!! $locales !!};
</script> </script>
<script src="{{ mix('js/manifest.js') }}"></script> <script src="{{ mix('js/manifest.js') }}"></script>