diff --git a/src/layouts/access-denied/access-denied.vue b/src/layouts/access-denied/access-denied.vue
new file mode 100644
index 00000000..d11870bb
--- /dev/null
+++ b/src/layouts/access-denied/access-denied.vue
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+ Unauthorized Access
+
+
+
+
+
+
+
+
+
+
diff --git a/src/router/index.js b/src/router/index.js
index bcf2fd46..1b2e8ace 100644
--- a/src/router/index.js
+++ b/src/router/index.js
@@ -1,3 +1,4 @@
+/* eslint-disable no-use-before-define */
import { createWebHistory, createRouter } from 'vue-router';
import lazyLoadComponent from '@/router/dynamic-routing/component-loader';
import issPageValues from '@/router/router-constants/issPage-values';
@@ -6,11 +7,8 @@ import { useMainStore } from '@/store';
import eventBus from '@/helpers/event-bus/event-bus';
import { globalEvents, globalEventTypes } from '@/constants/events';
import baseMixin from '@/mixins/base-mixin';
-import {
- getDeviceIdValue,
- updateOrCreateISSCookie,
- updateSessionIdCookie
-} from '@/helpers/cookie-helper';
+import { isSavedSessionStillActive } from '@/helpers/session-helper';
+import { getDeviceIdValue, getISSCookie, updateOrCreateISSCookie, updateSessionIdCookie } from '@/helpers/cookie-helper';
import { experimentTriggers } from '@/constants/experiments';
import applicationConfig from '@/constants/application-config';
@@ -23,29 +21,52 @@ const routes = [
name: 'root',
async beforeEnter(to, from, next) {
try {
- to.query.issPage = !to.query.issPage
- ? issPageValues.WELCOME_PAGE
- : to.query.issPage;
+ const issPageToUse = !to.query.issPage ? issPageValues.WELCOME_PAGE : to.query.issPage;
+
+ if ((issPageToUse === issPageValues.ACCESS_DENIED
+ || (issPageToUse !== issPageValues.ENTRY_PAGE && !useMainStore().issConfig.accountNumber))
+ && process.env.VUE_APP_CURRENT_ENVIRONMENT !== 'Localhost'
+ ) {
+ return await GoToAccessIsDenied(next);
+ }
// Do not run these for the main entry page - as it is not part of the user flow.
- if (to.query.issPage !== issPageValues.ENTRY_PAGE) {
+ if (issPageToUse !== issPageValues.ENTRY_PAGE) {
if (analyticsMixin.methods.noSession()) {
await analyticsMixin.methods.initSession();
} else {
updateSessionIdCookie();
}
- await runExperiments(to.query.issPage);
+ await runExperiments(issPageToUse); // fmg has this further down
+ }
+
+ // If the saved session has timed out, clear the session, execute 404 logic.
+ if (getISSCookie() !== null && !isSavedSessionStillActive()) {
+ // await baseMixin.methods.dispatchStoreAction(storeActions.RESET_STATE);
+ await GoToStartOn404(next);
}
// Process ISS cookie.
updateOrCreateISSCookie();
- if (router.hasRoute(to.query.issPage)) {
- return next({ name: to.query.issPage, query: to.query, params: to.params });
+ if (router.hasRoute(issPageToUse)) {
+ // Since our route is already in scope, we can grab the component and call the arePagePrerequisitesValid function.
+ let component = router.getRoutes().filter((x) => x.name === issPageToUse)[0].components;
+
+ // If the component hasn't been loaded fully, load it before we check prerequisites.
+ if (component.default.methods === undefined) {
+ component = await component.default();
+ }
+
+ if (!arePagePrerequisitesValid(component)) {
+ await GoToStartOn404(next);
+ }
+
+ return next({ name: issPageToUse, query: to.query, params: to.params });
}
- const routeData = await GetRouteInfoFromPageName(to.query.issPage);
+ const routeData = await GetRouteInfoFromPageName(issPageToUse);
if (routeData[0].name.toLowerCase() === 'error') {
throw new Error('Page not found!');
@@ -58,6 +79,19 @@ const routes = [
component: routeData[0].component
});
+ // Call the next components arePagePrerequisitesValid method before load.
+ // If it returns false, use the 404 logic.
+ const nextComponent = await router
+ .getRoutes()
+ .filter((x) => x.name === routeData[0].name)[0]
+ .components.default();
+
+ if (!arePagePrerequisitesValid(nextComponent)) {
+ const tempMsgCopy = 'Pre Requisites failed, need to handle. Default is Welcome Page.';
+ const tempMsgHeadline = `${issPageToUse}: pre-req failed...`;
+ await GoToStartOn404(next, tempMsgCopy, tempMsgHeadline);
+ }
+
// Assign current query string parameters, as well as our issPage one.
next({
name: routeData[0].name,
@@ -66,7 +100,7 @@ const routes = [
});
} catch (error) {
window.console.warn(error);
- GoToStartOn404(next);
+ await GoToStartOn404(next);
}
return null;
}
@@ -76,15 +110,13 @@ const routes = [
const router = createRouter({
history: createWebHistory('/'),
routes,
- scrollBehavior(to, from, savedPosition) {
+ scrollBehavior() {
// always scroll to top
return { top: 0 };
}
});
-router.afterEach((to, from) => {
- /*eslint-disable-line*/
-
+router.afterEach((to) => {
const store = useMainStore();
// Update lastPageVisited in the store
store.updateLastPageVisited(to.name);
@@ -119,36 +151,33 @@ async function GetRouteInfoFromPageName(pageName) {
}
// Use this navigation when you need to call next() explicitly. beforeRouteEnter is a good example.
-router.overrideNavigation = (scenario,
+router.overrideNavigation = (
+ scenario,
currentRoute,
next,
isSavingNavigation,
optionalQuery = {},
optionalParams = {},
- optionalPageData) => {
- navigate(scenario,
- currentRoute,
- isSavingNavigation,
- optionalQuery,
- optionalParams,
- optionalPageData);
+ optionalPageData = {}
+) => {
+ navigate(
+ scenario, currentRoute, isSavingNavigation, optionalQuery, optionalParams, optionalPageData
+ );
next();
};
-router.navigate = (scenario,
- currentRoute,
- optionalQuery = {},
- optionalParams = {},
- optionalPageData = {}) => {
- navigate(scenario, currentRoute, optionalQuery, optionalParams, optionalPageData);
+router.navigate = (
+ scenario, currentRoute, optionalQuery = {}, optionalParams = {}, optionalPageData = {}
+) => {
+ navigate(
+ scenario, currentRoute, optionalQuery, optionalParams, optionalPageData
+ );
};
// Navigate to the next route, depending on the scenario.
-function navigate(scenario,
- currentRoute,
- optionalQuery = {},
- optionalParams = {},
- optionalPageData = {}) {
+function navigate(
+ scenario, currentRoute, optionalQuery = {}, optionalParams = {}, optionalPageData = {}
+) {
/*eslint-disable-line*/
if (!scenario) {
window.console.error('No scenario provided. Please review the routing table.');
@@ -172,9 +201,7 @@ function navigate(scenario,
// Update page data to the store for next page if provided. Otherwise, keep existing page data or set to empty object
const existingPageDataForPage = useMainStore().pageData(matchingScenarioMap.destinationIssPageValue);
baseMixin.methods.savePageDataToStore(matchingScenarioMap.destinationIssPageValue,
- Object.keys(optionalPageData).length > 0
- ? optionalPageData
- : existingPageDataForPage ?? {});
+ Object.keys(optionalPageData).length > 0 ? optionalPageData : existingPageDataForPage ?? {});
// We're always pushing the same path, just changing query strings.
// Make sure our optional query strings get combined with our issPage one.
@@ -194,7 +221,7 @@ function navigate(scenario,
function navigateToUrl(url, optionalQuery = {}) {
// possibly show some loading screen in the future here.
const externalUrl = new URL(url);
- // eslint-disable-next-line no-restricted-syntax
+ // eslint-disable-next-line no-restricted-syntax, guard-for-in
for (const queryKey in optionalQuery) {
externalUrl.searchParams.append(queryKey, optionalQuery[queryKey]);
}
@@ -207,9 +234,7 @@ function getNavigationMap(scenario, currentRoute) {
const issPageValue = currentRoute.query.issPage;
try {
const matchedQueryValue = routingTable(useMainStore())
- .filter((item) =>
- item.issPageValue === issPageValue
- && item.maps.filter((map) => map.scenario === scenario).length > 0);
+ .filter((item) => item.issPageValue === issPageValue && item.maps.filter((map) => map.scenario === scenario).length > 0);
const maps = matchedQueryValue ? matchedQueryValue.map((m) => m.maps.filter((map) => map.scenario === scenario))[0] : undefined;
@@ -220,7 +245,21 @@ function getNavigationMap(scenario, currentRoute) {
}
}
-function GoToStartOn404(next) {
+async function GoToAccessIsDenied(next) {
+ const errorPageName = issPageValues.ACCESS_DENIED;
+ router.addRoute({
+ path: '/',
+ name: errorPageName,
+ component: lazyLoadComponent(errorPageName)
+ });
+
+ next({
+ name: errorPageName,
+ query: { issPage: errorPageName }
+ });
+}
+
+async function GoToStartOn404(next, msgCopy = null, msgHeadline = null) {
const errorPageName = issPageValues.WELCOME_PAGE;
router.addRoute({
path: '/',
@@ -229,14 +268,12 @@ function GoToStartOn404(next) {
});
// Put item on the bus
- eventBus.addEventToBus(globalEvents.Categories.GLOBAL_ALERT,
- globalEvents.SubCategories.PAGE_NOT_FOUND,
- {
- isDismissible: true,
- messageCopy: 'You can get a quote by starting on this page.',
- messageHeadline: "We're sorry, something went wrong.",
- type: globalEventTypes.Danger
- });
+ eventBus.addEventToBus(globalEvents.Categories.GLOBAL_ALERT, globalEvents.SubCategories.PAGE_NOT_FOUND, {
+ isDismissible: true,
+ messageCopy: msgCopy ?? 'You can get a quote by starting on this page.',
+ messageHeadline: msgHeadline ?? "We're sorry, something went wrong.",
+ type: globalEventTypes.Danger
+ });
next({
name: errorPageName,
@@ -244,6 +281,11 @@ function GoToStartOn404(next) {
});
}
+// Checks arePagePrerequisitesValid on the component passed in.
+function arePagePrerequisitesValid(component) {
+ return component.default.methods.arePagePrerequisitesValid === undefined || component.default.methods.arePagePrerequisitesValid();
+}
+
// Run SiteEntry and PageEntry triggers for experiments
async function runExperiments(nextPage) {
const store = useMainStore();
diff --git a/src/router/router-constants/issPage-values.js b/src/router/router-constants/issPage-values.js
index 9ddfab8c..68ad4a08 100644
--- a/src/router/router-constants/issPage-values.js
+++ b/src/router/router-constants/issPage-values.js
@@ -1,4 +1,5 @@
const issPageValues = Object.freeze({
+ ACCESS_DENIED: 'access-denied',
ENTRY_PAGE: 'entry-page',
WELCOME_PAGE: 'welcome-page',
diff --git a/src/router/router-constants/routing-table.js b/src/router/router-constants/routing-table.js
index 4af22d4f..7830bac3 100644
--- a/src/router/router-constants/routing-table.js
+++ b/src/router/router-constants/routing-table.js
@@ -319,6 +319,15 @@ const routingTable = () => [
}
]
},
+ {
+ issPageValue: issPageValues.ACCESS_DENIED,
+ maps: [
+ {
+ scenario: navigationScenarios.CLICKED_BACK,
+ destinationIssPageValue: issPageValues.ACCESS_DENIED
+ }
+ ]
+ },
{
issPageValue: issPageValues.ENTRY_PAGE,
maps: [
diff --git a/vue.config.js b/vue.config.js
index 5018024e..a13ba34c 100644
--- a/vue.config.js
+++ b/vue.config.js
@@ -1,14 +1,14 @@
+/* eslint-disable max-len */
process.env.VUE_APP_CONSUMER_CF_DISTRO = 'https://digitalapi.dev.safelite.io';
process.env.VUE_APP_CURRENT_ENVIRONMENT = 'Localhost';
-process.env.VUE_APP_GOOGLE_PLACES_API_KEY
- = 'AIzaSyCuLhQcDdZTTb4JzpUFms1OCch2dk5lHF0';
+process.env.VUE_APP_GOOGLE_PLACES_API_KEY = 'AIzaSyCuLhQcDdZTTb4JzpUFms1OCch2dk5lHF0';
// GA & GTM
// NOTE: Using the old ISS site GTM Cotnainer ID for now, will create a new one soon.
-process.env.VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY
- = "(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src='https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);})(window,document,'script','dataLayer','GTM-KKNWZ3');";
-process.env.VUE_APP_GOOGLE_TAG_MANAGER_NOSCRIPT_FRAME_SRC
- = 'https://www.googletagmanager.com/ns.html?id=GTM-KKNWZ3>m_auth=amlAYNhxUxuskQo7jmjadg>m_preview=env-38>m_cookies_win=x';
+process.env.VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY =
+ "(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src='https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);})(window,document,'script','dataLayer','GTM-KKNWZ3');";
+process.env.VUE_APP_GOOGLE_TAG_MANAGER_NOSCRIPT_FRAME_SRC =
+ 'https://www.googletagmanager.com/ns.html?id=GTM-KKNWZ3>m_auth=amlAYNhxUxuskQo7jmjadg>m_preview=env-38>m_cookies_win=x';
module.exports = {
publicPath: '/',