added user verification option in admin settings

This commit is contained in:
Milos Holba
2021-05-20 21:18:28 +02:00
parent 32bc3bacc0
commit 0139cc92bf
11 changed files with 117 additions and 14 deletions

View File

@@ -54,6 +54,10 @@ class CreateNewUser implements CreatesNewUsers
'storage_capacity' => $settings['storage_default'],
]);
if(!get_setting('user_verification')) {
$user->markEmailAsVerified();
}
UserSettings::reguard();
return $user;

View File

@@ -9,6 +9,7 @@ use App\Models\Folder;
use App\Models\Setting;
use Illuminate\Support\Str;
use App\Services\SetupService;
use Illuminate\Support\Carbon;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Storage;
@@ -87,6 +88,7 @@ class SetupDevEnvironment extends Command
'role' => 'admin',
'email' => 'howdy@hi5ve.digital',
'password' => bcrypt('vuefilemanager'),
'email_verified_at' => Carbon::now(),
]);
$user
@@ -127,6 +129,7 @@ class SetupDevEnvironment extends Command
'role' => 'user',
'email' => $this->faker->email,
'password' => bcrypt('vuefilemanager'),
'email_verified_at' => Carbon::now(),
]);
$newbie

View File

@@ -26,6 +26,7 @@ class AuthController extends Controller
return [
'name' => $user->settings->name,
'avatar' => $user->settings->avatar,
'verified' => $user->email_verified_at ? true : false
];
}
}

View File

@@ -178,8 +178,10 @@ class AccountController extends Controller
* @param User $user
* @return ResponseFactory|\Illuminate\Http\Response
*/
public function email_verify(User $user, Request $request)
public function email_verify($id, Request $request)
{
$user = User::find($id);
if (!$request->hasValidSignature()) {
return response("Invalid/Expired url provided.", 401);
}
@@ -188,7 +190,7 @@ class AccountController extends Controller
$user->markEmailAsVerified();
}
return redirect()->to('/');
return redirect()->to('/sign-in');
}
/**
@@ -196,13 +198,15 @@ class AccountController extends Controller
*
* @return ResponseFactory|\Illuminate\Http\Response
*/
public function resend_verify_email()
public function resend_verify_email(Request $request)
{
if (Auth::user()->hasVerifiedEmail()) {
$user = User::whereEmail($request->input('email'))->first();
if ($user->hasVerifiedEmail()) {
return response("Email already verified.", 204);
}
Auth::user()->sendEmailVerificationNotification();
$user->sendEmailVerificationNotification();
return response("Email verification link sent on your email", 200);
}

View File

@@ -291,6 +291,8 @@ return [
'admin_settings.email.username_plac' => 'Type your mail username',
'admin_settings.others.allow_registration' => 'Allow User Registration',
'admin_settings.others.allow_registration_help' => 'You can disable public registration for new users. You will still able to <br/>create new users in administration panel.',
'admin_settings.others.allow_user_verification' => 'Allow User Email Verification',
'admin_settings.others.allow_user_verification_help' => 'Turn on, if you want to allow user email verification.',
'admin_settings.others.cache_clear' => 'Clear Cache',
'admin_settings.others.cache_disclaimer' => 'Did you change anything in your .env file or change your Stripe credentials? Then clear your cache.',
'admin_settings.others.contact_email' => 'Contact Email',
@@ -472,6 +474,9 @@ return [
'page_sign_in.placeholder_password' => 'Type your password',
'page_sign_in.subtitle' => 'Confirm you by your password',
'page_sign_in.title' => 'Are You {name}?',
'page_not_verified.subtitle' => 'Your account is not verified. Before login, verify your account please.',
'page_not_verified.resend_text' => 'Do you want resend verification email?',
'page_not_verified.resend_button' => 'Resend verification email.',
'popup_create_folder.folder_default_name' => 'New Folder',
'popup_create_folder.label' => 'Type Name',
'popup_create_folder.placeholder' => 'Type your name',

View File

@@ -20,7 +20,7 @@
"/chunks/app-language.js": "/chunks/app-language.js?id=14b28923d876241b4324",
"/chunks/app-language~chunks/app-settings~chunks/dashboard~chunks/invoices~chunks/page-edit~chunks/pag~824d674f.js": "/chunks/app-language~chunks/app-settings~chunks/dashboard~chunks/invoices~chunks/page-edit~chunks/pag~824d674f.js?id=53e545b823ce2e687b31",
"/chunks/app-language~chunks/dashboard~chunks/files~chunks/invoices~chunks/pages~chunks/plans~chunks/s~38c276fc.js": "/chunks/app-language~chunks/dashboard~chunks/files~chunks/invoices~chunks/pages~chunks/plans~chunks/s~38c276fc.js?id=f90c5804695eeea92af0",
"/chunks/app-others.js": "/chunks/app-others.js?id=314e16368587d44da0fe",
"/chunks/app-others.js": "/chunks/app-others.js?id=1af00eb21fae95d927c0",
"/chunks/app-payments.js": "/chunks/app-payments.js?id=a8167d5a9383b34ac322",
"/chunks/app-settings.js": "/chunks/app-settings.js?id=7036abc45d63af4fe972",
"/chunks/app-setup.js": "/chunks/app-setup.js?id=99d86e5e53e0961538d4",
@@ -72,7 +72,7 @@
"/chunks/shared/authenticate.js": "/chunks/shared/authenticate.js?id=238c362399a4018549bd",
"/chunks/shared/file-browser.js": "/chunks/shared/file-browser.js?id=d630c473dc6b751ec50f",
"/chunks/shared/single-file.js": "/chunks/shared/single-file.js?id=040a7241ea133456200c",
"/chunks/sign-in.js": "/chunks/sign-in.js?id=a694e3863cefe7da1daa",
"/chunks/sign-in.js": "/chunks/sign-in.js?id=649d051ab2fa0118f313",
"/chunks/sign-up.js": "/chunks/sign-up.js?id=f5634301e476029d6fa1",
"/chunks/stripe-credentials.js": "/chunks/stripe-credentials.js?id=7a9a78fcdfebbeff5c3d",
"/chunks/subscription-plans.js": "/chunks/subscription-plans.js?id=314fdc603b7dd04d2b9d",
@@ -92,5 +92,34 @@
"/vendors~chunks/admin~chunks/admin-account~chunks/app-appearance~chunks/app-billings~chunks/app-email~2fac28cc.js": "/vendors~chunks/admin~chunks/admin-account~chunks/app-appearance~chunks/app-billings~chunks/app-email~2fac28cc.js?id=57c854adb91ed9a9d088",
"/vendors~chunks/admin~chunks/admin-account~chunks/app-appearance~chunks/app-billings~chunks/app-email~d5e36d91.js": "/vendors~chunks/admin~chunks/admin-account~chunks/app-appearance~chunks/app-billings~chunks/app-email~d5e36d91.js?id=170765b4fd923b62195c",
"/vendors~chunks/files~chunks/platform~chunks/shared~chunks/shared-files~chunks/shared/file-browser~ch~52c14f2e.js": "/vendors~chunks/files~chunks/platform~chunks/shared~chunks/shared-files~chunks/shared/file-browser~ch~52c14f2e.js?id=66afa0e341251a68c3d3",
"/vendors~chunks/platform~chunks/shared.js": "/vendors~chunks/platform~chunks/shared.js?id=eb141834bc24b72d8e92"
"/vendors~chunks/platform~chunks/shared.js": "/vendors~chunks/platform~chunks/shared.js?id=eb141834bc24b72d8e92",
"/chunks/app-others.4a1880c5e5279e443415.hot-update.js": "/chunks/app-others.4a1880c5e5279e443415.hot-update.js",
"/chunks/app-others.65fc70ed6cd855b5f739.hot-update.js": "/chunks/app-others.65fc70ed6cd855b5f739.hot-update.js",
"/chunks/app-others.ec7781305c199afd7ac1.hot-update.js": "/chunks/app-others.ec7781305c199afd7ac1.hot-update.js",
"/chunks/app-others.8b1366ac8c6c3d51a360.hot-update.js": "/chunks/app-others.8b1366ac8c6c3d51a360.hot-update.js",
"/chunks/app-others.ee1c494b6e7c65ef457d.hot-update.js": "/chunks/app-others.ee1c494b6e7c65ef457d.hot-update.js",
"/chunks/app-others.bdcb16d88a2f534975b1.hot-update.js": "/chunks/app-others.bdcb16d88a2f534975b1.hot-update.js",
"/chunks/app-others.d7ea54db66f0d57ed713.hot-update.js": "/chunks/app-others.d7ea54db66f0d57ed713.hot-update.js",
"/chunks/app-others.f5d5675c971c27d1f7e9.hot-update.js": "/chunks/app-others.f5d5675c971c27d1f7e9.hot-update.js",
"/chunks/sign-in.184793cba19c4befae4f.hot-update.js": "/chunks/sign-in.184793cba19c4befae4f.hot-update.js",
"/chunks/sign-in.a9ecea30dd01a6e837ed.hot-update.js": "/chunks/sign-in.a9ecea30dd01a6e837ed.hot-update.js",
"/chunks/sign-in.cdc378238cd3ebffb0f4.hot-update.js": "/chunks/sign-in.cdc378238cd3ebffb0f4.hot-update.js",
"/chunks/sign-in.50ca919fad3f9a6b0c7a.hot-update.js": "/chunks/sign-in.50ca919fad3f9a6b0c7a.hot-update.js",
"/chunks/sign-in.2f00413d818bda25eb35.hot-update.js": "/chunks/sign-in.2f00413d818bda25eb35.hot-update.js",
"/chunks/sign-in.2a7a8d0a41dd6c30c0ed.hot-update.js": "/chunks/sign-in.2a7a8d0a41dd6c30c0ed.hot-update.js",
"/chunks/sign-in.8ea3e1a7d9dd1a70b024.hot-update.js": "/chunks/sign-in.8ea3e1a7d9dd1a70b024.hot-update.js",
"/chunks/sign-in.dc398a4251e46ac97944.hot-update.js": "/chunks/sign-in.dc398a4251e46ac97944.hot-update.js",
"/chunks/sign-in.3adea8208d6fc3821797.hot-update.js": "/chunks/sign-in.3adea8208d6fc3821797.hot-update.js",
"/chunks/sign-in.9efe4a4c966f1960aba3.hot-update.js": "/chunks/sign-in.9efe4a4c966f1960aba3.hot-update.js",
"/chunks/sign-in.6d963727e5c35fb26e6e.hot-update.js": "/chunks/sign-in.6d963727e5c35fb26e6e.hot-update.js",
"/chunks/sign-in.8d5c9b43872d4f560074.hot-update.js": "/chunks/sign-in.8d5c9b43872d4f560074.hot-update.js",
"/chunks/sign-in.de26ebb8f5305618ba79.hot-update.js": "/chunks/sign-in.de26ebb8f5305618ba79.hot-update.js",
"/chunks/sign-in.7406fea0a099e3a8665a.hot-update.js": "/chunks/sign-in.7406fea0a099e3a8665a.hot-update.js",
"/chunks/sign-in.8da4f2ef76780a6c56c0.hot-update.js": "/chunks/sign-in.8da4f2ef76780a6c56c0.hot-update.js",
"/chunks/sign-in.bf19d64759c9e9b5239f.hot-update.js": "/chunks/sign-in.bf19d64759c9e9b5239f.hot-update.js",
"/chunks/sign-in.28b0b83732ce321c4e39.hot-update.js": "/chunks/sign-in.28b0b83732ce321c4e39.hot-update.js",
"/chunks/sign-up.1a6fc69e814f5c2081cf.hot-update.js": "/chunks/sign-up.1a6fc69e814f5c2081cf.hot-update.js",
"/chunks/sign-up.2eeea0f4a373d3154966.hot-update.js": "/chunks/sign-up.2eeea0f4a373d3154966.hot-update.js",
"/chunks/sign-up.824b863643bbc69324a0.hot-update.js": "/chunks/sign-up.824b863643bbc69324a0.hot-update.js",
"/chunks/sign-up.1ca02954735d934e513e.hot-update.js": "/chunks/sign-up.1ca02954735d934e513e.hot-update.js"
}

View File

@@ -58,6 +58,24 @@
</div>
</div>
<div class="block-wrapper">
<div class="input-wrapper">
<div class="inline-wrapper">
<div class="switch-label">
<label class="input-label">
{{ $t('admin_settings.others.allow_user_verification') }}:
</label>
<small class="input-help" v-html="$t('admin_settings.others.allow_user_verification_help')"></small>
</div>
<SwitchInput @input="$updateText('/admin/settings', 'user_verification', app.userVerification)"
v-model="app.userVerification"
class="switch"
:state="app.userVerification"
/>
</div>
</div>
</div>
<FormLabel class="mt-70">
{{ $t('admin_settings.others.section_others') }}
</FormLabel>
@@ -173,7 +191,7 @@
mounted() {
axios.get('/api/admin/settings', {
params: {
column: 'contact_email|google_analytics|storage_default|registration|storage_limitation|mimetypes_blacklist|upload_limit'
column: 'contact_email|google_analytics|storage_default|registration|storage_limitation|mimetypes_blacklist|upload_limit|user_verification'
}
})
.then(response => {
@@ -186,7 +204,8 @@
userRegistration: parseInt(response.data.registration),
storageLimitation: parseInt(response.data.storage_limitation),
mimetypesBlacklist : response.data.mimetypes_blacklist,
uploadLimit: response.data.upload_limit
uploadLimit: response.data.upload_limit,
userVerification: response.data.user_verification
}
})
}

View File

@@ -61,6 +61,19 @@
</router-link>
</span>
</AuthContent>
<AuthContent name="not-verified" :visible="false">
<div class="user" v-if="checkedAccount">
<img class="user-avatar" :src="checkedAccount.avatar" :alt="checkedAccount.name">
<h1>{{ checkedAccount.name }}</h1>
<h2>{{ $t('page_not_verified.subtitle') }}</h2>
</div>
<span class="additional-link"> {{ $t('page_not_verified.resend_text') }}
<a @click="resendEmail" class="text-theme">{{ $t('page_not_verified.resend_button') }} </a>
</span>
</AuthContent>
</AuthContentWrapper>
</template>
@@ -110,6 +123,13 @@
}
})
},
resendEmail() {
axios.
post('/api/user/email/resend/verify', {
email: this.loginEmail
})
.then(console.log('send'))
},
async logIn() {
// Validate fields
@@ -164,6 +184,13 @@
if (!isValid) return;
if(!this.checkedAccount.verified) {
this.goToAuthPage('not-verified')
return
}
// Start loading
this.isLoading = true

View File

@@ -55,6 +55,7 @@
allowHomepage: {{ $settings->allow_homepage ?? 1 }},
userRegistration: {{ $settings->registration ?? 1 }},
userVerification: {{ $settings->user_verification ?? 0 }},
storageLimit: {{ $settings->storage_limitation ?? 1 }},
storageDefaultSpace: {{ $settings->storage_default ?? 5 }},
storageDefaultSpaceFormatted: '{{ isset($settings->storage_default) ? format_gigabytes($settings->storage_default) : format_gigabytes(5) }}',

View File

@@ -8,12 +8,12 @@ use App\Http\Controllers\User\PaymentMethodsController;
Route::post('/check', [AuthController::class, 'check_account']);
// Email verification
Route::get('email/verify/{user}', [AccountController::class, 'email_verify'])->name('verification.verify');
Route::get('/email/verify/{id}', [AccountController::class, 'email_verify'])->name('verification.verify');
Route::post('/email/resend/verify', [AccountController::class, 'resend_verify_email'])->name('verification.send');
Route::group(['middleware' => ['auth:sanctum']], function () {
// Account
Route::patch('/relationships/settings', [AccountController::class, 'update_user_settings']);
Route::post('/email/resend/verify', [AccountController::class, 'resend_verify_email']);
Route::delete('/token/revoke/{token}', [AccountController::class, 'revoke_token']);
Route::post('/token/create', [AccountController::class, 'create_token']);
Route::post('/password', [AccountController::class, 'change_password']);

View File

@@ -14,6 +14,7 @@ use Storage;
use Notification;
use Tests\TestCase;
use App\Models\Folder;
use Illuminate\Support\Facades\URL;
class UserAccountTest extends TestCase
{
@@ -265,10 +266,19 @@ class UserAccountTest extends TestCase
*/
public function it_user_email_verify()
{
// TODO:make request with signature
$user = User::factory(User::class)
->create();
->create([
'email_verified_at' => null
]);
$this->getJson("/api/user/email/verify/$user->id");
$verificationUrl = URL::temporarySignedRoute(
'verification.verify',
now()->addMinutes(60),
['id' => $user->id, 'hash' => sha1($user->email)]
);
$this->getJson($verificationUrl);
$this->assertNotNull($user->email_verified_at);
}