Merge remote-tracking branch 'origin/email-verification'

# Conflicts:
#	composer.lock
#	public/mix-manifest.json
#	tests/TestCase.php
This commit is contained in:
Peter Papp
2021-07-15 14:00:43 +02:00
43 changed files with 988 additions and 12292 deletions
@@ -0,0 +1,44 @@
<template>
<div class="select-box" :class="[isClicked ? 'bg-theme' : 'is-deactive'] ">
<CheckIcon v-if="isClicked" class="icon" size="17" />
</div>
</template>
<script>
import { CheckIcon } from 'vue-feather-icons'
export default {
name: 'CheckBox',
props: [ 'isClicked' ],
components: { CheckIcon }
}
</script>
<style lang="scss" scoped>
@import '@assets/vuefilemanager/_variables';
.select-box {
min-width: 20px;
min-height: 20px;
display: flex;
justify-content: center;
align-items: center;
border-radius: 5px;
.icon {
stroke: white;
}
}
.is-deactive {
background-color: darken($light_background, 5%);
}
@media (prefers-color-scheme: dark) {
.is-deactive {
background-color: lighten($dark_mode_foreground, 10%);
}
}
</style>
@@ -7,11 +7,7 @@
<div class="icon-item">
<!-- MultiSelecting for the mobile version -->
<div :class="{'check-select-folder' : this.item.type === 'folder', 'check-select' : this.item.type !== 'folder'}" v-if="mobileMultiSelect">
<div class="select-box" :class="{'select-box-active' : isClicked } ">
<CheckIcon v-if="isClicked" class="icon" size="17" />
</div>
</div>
<CheckBox v-if="mobileMultiSelect" :is-clicked="isClicked" class="check-box"/>
<!--If is file or image, then link item-->
<span v-if="isFile || (isImage && !item.thumbnail)" class="file-icon-text text-theme">
@@ -65,8 +61,9 @@
</template>
<script>
import {LinkIcon, UserPlusIcon, CheckIcon, MoreHorizontalIcon} from 'vue-feather-icons'
import {LinkIcon, UserPlusIcon, MoreHorizontalIcon} from 'vue-feather-icons'
import FolderIcon from '@/components/FilesView/FolderIcon'
import CheckBox from '@/components/FilesView/CheckBox'
import {debounce} from 'lodash'
import {mapGetters} from 'vuex'
import {events} from '@/bus'
@@ -77,9 +74,9 @@ export default {
components: {
MoreHorizontalIcon,
UserPlusIcon,
CheckIcon,
LinkIcon,
FolderIcon,
CheckBox,
LinkIcon,
},
computed: {
...mapGetters([
@@ -308,7 +305,7 @@ export default {
@import '@assets/vuefilemanager/_variables';
@import '@assets/vuefilemanager/_mixins';
.check-select {
.check-box {
margin-right: 10px;
margin-left: 3px;
position: absolute;
@@ -317,35 +314,6 @@ export default {
left: 0px;
}
.check-select-folder {
margin-right: 10px;
margin-left: 3px;
position: absolute;
top: 8px;
z-index: 5;
left: 10px;
}
.select-box {
width: 20px;
height: 20px;
background-color: $light_background;
display: flex;
justify-content: center;
align-items: center;
border-radius: 5px;
box-shadow: 0 3px 15px 2px hsla(220, 36%, 16%, 0.05);
}
.select-box-active {
background-color: $theme;
.icon {
stroke: white;
}
}
.show-actions {
cursor: pointer;
padding: 4px 26px;
@@ -582,18 +550,6 @@ export default {
@media (prefers-color-scheme: dark) {
.select-box {
background-color: lighten($dark_mode_foreground, 10%);
}
.select-box-active {
background-color: lighten($theme, 5%);
.icon {
stroke: white;
}
}
.file-wrapper {
.icon-item {
@@ -10,11 +10,7 @@
>
<!-- MultiSelecting for the mobile version -->
<transition name="slide-from-left">
<div class="check-select" v-if="mobileMultiSelect">
<div class="select-box" :class="{'select-box-active' : isClicked } ">
<CheckIcon v-if="isClicked" class="icon" size="17" />
</div>
</div>
<CheckBox v-if="mobileMultiSelect" :is-clicked="isClicked" class="check-box"/>
</transition>
<!--Thumbnail for item-->
@@ -72,8 +68,9 @@
</template>
<script>
import {LinkIcon, UserPlusIcon, CheckIcon, MoreVerticalIcon} from 'vue-feather-icons'
import {LinkIcon, UserPlusIcon, MoreVerticalIcon} from 'vue-feather-icons'
import FolderIcon from '@/components/FilesView/FolderIcon'
import CheckBox from '@/components/FilesView/CheckBox'
import {debounce} from 'lodash'
import {mapGetters} from 'vuex'
import {events} from '@/bus'
@@ -87,7 +84,7 @@ export default {
MoreVerticalIcon,
UserPlusIcon,
FolderIcon,
CheckIcon,
CheckBox,
LinkIcon,
},
computed: {
@@ -335,28 +332,9 @@ export default {
transform: translateX(100%);
}
.check-select {
.check-box {
margin-right: 15px;
margin-left: 6px;
.select-box {
width: 20px;
height: 20px;
background-color: darken($light_background, 5%);
display: flex;
justify-content: center;
align-items: center;
border-radius: 5px;
}
.select-box-active {
background-color: $theme;
.icon {
stroke: white;
}
}
}
.file-wrapper {
@@ -543,20 +521,6 @@ export default {
}
@media (prefers-color-scheme: dark) {
.check-select {
.select-box {
background-color: lighten($dark_mode_foreground, 10%);
}
.select-box-active {
background-color: $theme;
.icon {
stroke: white;
}
}
}
.file-wrapper {
.icon-item {
+28
View File
@@ -334,6 +334,24 @@ const routesShared = [
},
]
const routesAuth = [
{
name: 'SuccessfullyVerified',
path: '/successfully-verified',
component: () =>
import(/* webpackChunkName: "chunks/email-verified" */ './views/Auth/SuccessfullyEmailVerified'),
meta: {
requiresAuth: false
},
},
{
name: 'SuccessfullySend',
path: '/successfully-send',
component: () =>
import(/* webpackChunkName: "chunks/email-verified" */ './views/Auth/SuccessfullySendEmail'),
meta: {
requiresAuth: false
},
},
{
name: 'SignIn',
path: '/sign-in',
@@ -416,6 +434,16 @@ const routesUser = [
title: 'routes_title.settings_password'
},
},
{
name: 'Token',
path: '/platform/token',
component: () =>
import(/* webpackChunkName: "chunks/settings-password" */ './views/User/AccessToken'),
meta: {
requiresAuth: true,
title: 'routes_title.token'
},
},
{
name: 'Storage',
path: '/platform/settings/storage',
@@ -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: parseInt(response.data.user_verification)
}
})
}
+32
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,18 @@
}
})
},
resendEmail() {
axios.
post('/api/user/email/resend/verify', {
email: this.loginEmail
})
.then(
this.$router.push({name: 'SuccessfullySend'})
)
.catch(() => {
this.$isSomethingWrong()
})
},
async logIn() {
// Validate fields
@@ -164,6 +189,13 @@
if (!isValid) return;
if(!this.checkedAccount.verified) {
this.goToAuthPage('not-verified')
return
}
// Start loading
this.isLoading = true
+12 -6
View File
@@ -132,17 +132,23 @@
// Send request to get user token
axios
.post('/register', this.register)
.post('/api/register', this.register)
.then(() => {
// End loading
this.isLoading = false
// Set login state
this.$store.commit('SET_AUTHORIZED', true)
// Go to files page
this.$router.push({name: 'Files'})
if(! this.config.userVerification) {
// Set login state
this.$store.commit('SET_AUTHORIZED', true)
// Go to files page
this.$router.push({name: 'Files'})
} else {
// Go to SuccessfullySend page
this.$router.push({name: 'SuccessfullySend'})
}
})
.catch(error => {
@@ -0,0 +1,40 @@
<template>
<AuthContentWrapper>
<AuthContent :visible="true">
<img v-if="config.app_logo" class="logo" :src="$getImage(config.app_logo)" :alt="config.app_name">
<b v-if="! config.app_logo" class="auth-logo-text">{{ config.app_name }}</b>
<h1>{{ $t('page_email_successfully_verified.title') }}</h1>
<h2>{{ $t('page_email_successfully_verified.subtitle') }}</h2>
<a href="/sign-in">
<AuthButton icon="chevron-right" :text="$t('page_sign_in.button_log_in')"/>
</a>
</AuthContent>
</AuthContentWrapper>
</template>
<script>
import AuthContentWrapper from '@/components/Auth/AuthContentWrapper'
import AuthContent from '@/components/Auth/AuthContent'
import AuthButton from '@/components/Auth/AuthButton'
import {mapGetters} from 'vuex'
export default {
name: 'SuccessfullyEmailVerified',
components: {
AuthContentWrapper,
AuthContent,
AuthButton,
},
computed: {
...mapGetters(['config']),
},
}
</script>
<style scoped lang="scss">
@import '@assets/vuefilemanager/_auth-form';
@import '@assets/vuefilemanager/_auth';
</style>
@@ -0,0 +1,42 @@
<template>
<AuthContentWrapper>
<AuthContent :visible="true">
<img v-if="config.app_logo" class="logo" :src="$getImage(config.app_logo)" :alt="config.app_name">
<b v-if="! config.app_logo" class="auth-logo-text">{{ config.app_name }}</b>
<h1>{{ $t('page_email_successfully_send.title') }}</h1>
<h2>{{ $t('page_email_successfully_send.subtitle') }}</h2>
<span class="additional-link">
<router-link :to="{name: 'Homepage'}" class="text-theme">
{{ $t('go_home') }}
</router-link>
</span>
</AuthContent>
</AuthContentWrapper>
</template>
<script>
import AuthContentWrapper from '@/components/Auth/AuthContentWrapper'
import AuthContent from '@/components/Auth/AuthContent'
import AuthButton from '@/components/Auth/AuthButton'
import {mapGetters} from 'vuex'
export default {
name: 'SuccessfullySendEmail',
components: {
AuthContentWrapper,
AuthContent,
AuthButton,
},
computed: {
...mapGetters(['config']),
},
}
</script>
<style scoped lang="scss">
@import '@assets/vuefilemanager/_auth-form';
@import '@assets/vuefilemanager/_auth';
</style>
+11
View File
@@ -32,6 +32,15 @@
{{ $t('menu.password') }}
</div>
</router-link>
<router-link replace :to="{name: 'Token'}" class="menu-list-item link">
<div class="icon text-theme">
<key-icon size="17"></key-icon>
</div>
<div class="label text-theme">
{{ $t('menu.token') }}
</div>
</router-link>
</div>
</ContentGroup>
<ContentGroup title="Subscription" class="navigator" v-if="canShowSubscriptionSettings">
@@ -142,6 +151,7 @@
CloudIcon,
UserIcon,
LockIcon,
KeyIcon,
} from 'vue-feather-icons'
export default {
@@ -162,6 +172,7 @@
LockIcon,
Spinner,
InfoBox,
KeyIcon,
},
computed: {
...mapGetters(['user', 'config']),
+41
View File
@@ -0,0 +1,41 @@
<template>
<PageTab>
<PageTabGroup>
<FormLabel>{{ $t('user_token.title') }}</FormLabel>
</PageTabGroup>
</PageTab>
</template>
<script>
import PageTabGroup from '@/components/Others/Layout/PageTabGroup'
import FormLabel from '@/components/Others/Forms/FormLabel'
import PageTab from '@/components/Others/Layout/PageTab'
export default {
name: 'AccessToken',
components: {
PageTabGroup,
FormLabel,
PageTab
},
data () {
return {
tokens: undefined
}
},
created () {
axios.
get('/api/user/tokens')
.then(response => {
this.tokens = response.data
})
}
}
</script>
<style lang="scss" scoped>
@import '@assets/vuefilemanager/_variables';
@import '@assets/vuefilemanager/_mixins';
</style>
+1
View File
@@ -54,6 +54,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) }}',