Skip to content

Commit

Permalink
Merge pull request #2592 from NationalSecurityAgency/t#2490/account-v…
Browse files Browse the repository at this point in the history
…erification

T#2490/account verification
  • Loading branch information
dwalizer authored Jun 19, 2024
2 parents 6c989c3 + 16ada20 commit cf1b648
Show file tree
Hide file tree
Showing 8 changed files with 273 additions and 20 deletions.
36 changes: 36 additions & 0 deletions dashboard-prime/src/components/access/EmailVerificationSent.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<script setup>
import Logo1 from "@/components/brand/Logo1.vue";
import {useEmailVerificationInfo} from "@/components/access/UseEmailVerificationInfo.js";
const emailVerificationInfo = useEmailVerificationInfo()
</script>

<template>
<div>
<div class="flex justify-content-center text-center" data-cy="emailVerificationSentConfirmation">
<div class="" style="min-width: 20rem;">
<div class="mt-5">
<logo1 />
<div class="h3 mt-4 text-primary">Email Verification Sent!</div>
</div>
<Card>
<template #content>
<p>An email verification code has been sent to <span class="text-primary font-weight-bold">{{ emailVerificationInfo.email }}</span>.</p>
<p>Please check your email and confirm your email address to complete your SkillTree account creation.</p>
<div class="text-center">
<router-link to="/skills-login">
<SkillsButton class="p-2" data-cy="loginPage" icon="fas fa-sign-in-alt" label="Return to Login Page"></SkillsButton>
</router-link>
</div>
</template>
</Card>

</div>
</div>
</div>
</template>

<style scoped>
</style>
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<script setup>
import { ref, onMounted, watch } from 'vue';
import { useRouter } from 'vue-router';
import AccessService from "@/components/access/AccessService.js";
import LoadingContainer from "@/components/utils/LoadingContainer.vue";
import Logo1 from "@/components/brand/Logo1.vue";
import {useEmailVerificationInfo} from "@/components/access/UseEmailVerificationInfo.js";
const emailVerificationInfo = useEmailVerificationInfo()
const router = useRouter();
const props = defineProps({
countDown: {
type: Number,
default: 10,
},
token: {
type: String,
default: '',
},
email: {
type: String,
default: '',
},
});
const timer = ref(-1);
const loading = ref(true);
onMounted(() => {
verifyEmail();
});
const verifyEmail = () => {
const verification = { token: props.token, email: props.email };
AccessService.verifyEmail(verification).then(() => {
loading.value = false;
timer.value = props.countDown;
}).catch((err) => {
const params = {
email: props.email,
explanation: 'GeneralError',
};
if (err && err.response && err.response.data && err.response.data.errorCode === 'UserTokenExpired') {
params.explanation = 'UserTokenExpired';
}
emailVerificationInfo.setEmail(params.email)
emailVerificationInfo.setReason(params.explanation)
router.push({ name: 'RequestEmailVerification' });
});
};
watch(() => timer.value, (newValue) => {
if (newValue > 0) {
setTimeout(() => {
timer.value -= 1;
}, 1000);
} else {
router.push({ name: 'Login' });
}
})
</script>

<template>
<loading-container :is-loading="loading">
<div class="flex justify-content-center text-center" data-cy="emailConfirmation">
<div class="" style="min-width: 20rem;">
<div class="mt-5">
<logo1 />
<div class="h3 mt-4 text-primary">Email Address Successfully Confirmed!</div>
</div>
<Card>
<template #content>
<p>Your email address has been confirmed! You will be forwarded to the login page in {{ timer }} seconds.</p>
<div class="text-center">
<router-link to="/skills-login">
<SkillsButton class="p-2" data-cy="loginPage" icon="fas fa-sign-in-alt" label="Return to Login Page"></SkillsButton>
</router-link>
</div>
</template>
</Card>
</div>
</div>
</loading-container>
</template>

<style scoped>
</style>
6 changes: 5 additions & 1 deletion dashboard-prime/src/components/access/Login.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ import Logo1 from '@/components/brand/Logo1.vue'
import AccessService from '@/components/access/AccessService.js'
import InputGroup from 'primevue/inputgroup'
import InputGroupAddon from 'primevue/inputgroupaddon'
import { useEmailVerificationInfo } from '@/components/access/UseEmailVerificationInfo.js'
const appConfig = useAppConfig()
const emailVerificationInfo = useEmailVerificationInfo()
const schema = object({
username: string().required().email().min(appConfig.minUsernameLength).label('Email Address'),
Expand Down Expand Up @@ -61,7 +63,9 @@ const onSubmit = handleSubmit((values) => {
if (appConfig.verifyEmailAddresses) {
AccessService.userEmailIsVerified(values.username).then((result) => {
if (!result) {
router.push({ name: 'RequestEmailVerification', params: { email: values.username } })
emailVerificationInfo.setEmail(values.username)
emailVerificationInfo.setReason('NotVerified')
router.push({ name: 'RequestEmailVerification' })
} else {
performFormLogin(values)
}
Expand Down
5 changes: 4 additions & 1 deletion dashboard-prime/src/components/access/RequestAccount.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@ import { string } from 'yup';
import Logo1 from '@/components/brand/Logo1.vue';
import AccessService from '@/components/access/AccessService.js';
import InputGroupAddon from 'primevue/inputgroupaddon';
import {useEmailVerificationInfo} from "@/components/access/UseEmailVerificationInfo.js";
const authState = useAuthState()
const route = useRoute()
const router = useRouter()
const appConfig = useAppConfig()
const emailVerificationInfo = useEmailVerificationInfo()
const isRootAccount = route.meta.isRootAccount;
const createInProgress = ref(false);
Expand Down Expand Up @@ -45,7 +47,8 @@ const login = (firstName, lastName, email, password) => {
authState.configureSkillsClientForInception()
.then(() => {
if (verifyEmailAddresses.value) {
router.push({name: 'EmailVerificationSent', params: {email}});
emailVerificationInfo.setEmail(email)
router.push({name: 'EmailVerificationSent'});
} else if (route.query.redirect) {
router.push(route.query.redirect);
} else if (!isProgressAndRankingEnabled.value) {
Expand Down
59 changes: 59 additions & 0 deletions dashboard-prime/src/components/access/RequestEmailVerification.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<script setup>
import { computed } from 'vue';
import { useRouter } from 'vue-router';
import AccessService from "@/components/access/AccessService.js";
import Logo1 from "@/components/brand/Logo1.vue";
import {useEmailVerificationInfo} from "@/components/access/UseEmailVerificationInfo.js";
const emailVerificationInfo = useEmailVerificationInfo()
const router = useRouter();
const explanationReason = computed(() => {
if( emailVerificationInfo.reason === 'UserTokenExpired' ) {
return 'Your email verification code has expired. Please click the button below to resend a new verification code.';
} else if ( emailVerificationInfo.reason === 'GeneralError' ) {
return 'An error occurred while verifying your email address. Please click the button below to resend a new verification code.';
}
return '';
})
const resend = () => {
AccessService.resendEmailVerification(emailVerificationInfo.email).then(() => {
router.push({ name: 'EmailVerificationSent' });
});
};
</script>

<template>
<div>
<div class="flex w-full justify-content-center">
<div class="flex flex-column" style="min-width: 20rem;">
<div class="mt-5 mb-5 flex flex-column align-items-center" data-cy="confirmEmailTitle">
<logo1 />
<div class="h3 mt-4 text-primary">Email Verification is Required!</div>
</div>
<Card data-cy="confirmEmailExplanation">
<template #content>
<div v-if="explanationReason">
<p>{{explanationReason}}</p>
</div>
<div v-else>
<p>You must first validate your email address in order to start using SkillTree.</p>
<p>An email verification code has been sent to {{ emailVerificationInfo.email }}.</p>
<p>Please check your email and confirm your email address to complete your SkillTree account creation, or you can click the button below to resend a new verification code.</p>
</div>
<div class="text-center">
<SkillsButton variant="outline-primary" @click="resend" data-cy="resendConfirmationCodeButton" aria-label="Resend Email Confirmation Code" icon="fas fa-arrow-circle-right" label="Resend Email Confirmation Code">
</SkillsButton>
</div>
</template>
</Card>
</div>
</div>
</div>
</template>

<style scoped>
</style>
23 changes: 23 additions & 0 deletions dashboard-prime/src/components/access/UseEmailVerificationInfo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { computed, ref } from 'vue'
import { defineStore } from 'pinia'

export const useEmailVerificationInfo = defineStore('useEmailVerificationInfo', () => {
const emailVal = ref('')
const reasonVal = ref('')
const setEmail = (newEmail) => {
emailVal.value = newEmail
}
const email = computed(() => emailVal.value)

const setReason = (newReason) => {
reasonVal.value = newReason
}
const reason = computed(() => reasonVal.value)

return {
email,
setEmail,
reason,
setReason
}
})
39 changes: 39 additions & 0 deletions dashboard-prime/src/router/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ import ResetConfirmation from '@/components/access/ResetConfirmation.vue';
import ResetNotSupportedPage from '@/components/access/ResetNotSupportedPage.vue';
import RequestAccount from '@/components/access/RequestAccount.vue';
import UserAgreement from '@/components/access/UserAgreement.vue'
import EmailVerificationSent from "@/components/access/EmailVerificationSent.vue";
import EmailVerifiedConfirmation from "@/components/access/EmailVerifiedConfirmation.vue";
import RequestEmailVerification from "@/components/access/RequestEmailVerification.vue";

const routes = [
{
Expand Down Expand Up @@ -171,6 +174,42 @@ const routes = [
},
},
},
{
path: '/email-verification-sent',
name: 'EmailVerificationSent',
component: EmailVerificationSent,
props: true,
meta: {
requiresAuth: false,
announcer: {
message: 'Email Verification Sent',
},
},
},
{
path: '/verify-email/:token/:email',
name: 'EmailVerifiedConfirmation',
component: EmailVerifiedConfirmation,
props: true,
meta: {
requiresAuth: false,
announcer: {
message: 'Email Verification Confirmation',
},
},
},
{
path: '/request-email-verification',
name: 'RequestEmailVerification',
component: RequestEmailVerification,
props: true,
meta: {
requiresAuth: false,
announcer: {
message: 'Request Email Verification',
},
},
},
{
path: '/error',
name: 'ErrorPage',
Expand Down
Loading

0 comments on commit cf1b648

Please sign in to comment.