DigitalConsumer.ISS/src/layouts/entry-page/entry-page.vue
Alex Humphries 6734fb99b4 INSR-10100: Allow hiding certain fields on welcome page
- Update issConfig to include hiddenFields object based on client flags
- Update welcome-page to display fields based on issConfig.hiddenFields
2026-07-09 12:32:54 -04:00

324 lines
14 KiB
Vue

<template>
<p
v-show="unauthorized"
id="message">
Unauthorized Access.
</p>
</template>
<script>
// Supporting files
import issPageValues from '@/router/router-constants/issPage-values';
import { validateISSClientTag, validateISSClientSignature } from '@/helpers/clientauth-helper';
import { getISSCookie, updateOrCreateISSCookie } from '@/helpers/cookie-helper.js';
import { useMainStore } from '@/store';
import showIssLoadingModal from '@/helpers/loading-modal-helper';
import { toPossessive } from '@/helpers/text-helper';
import analyticsMixin from '@/mixins/analytics-mixin';
import routerParams from '@/router/router-constants/router-params';
export default {
name: 'entry-page',
components: {
},
mixins: [],
setup() {
const mainStore = useMainStore();
mainStore.populateInitialState(true);
return { mainStore };
},
data() {
return {
unauthorized: false
};
},
computed: {
},
async mounted() {
try {
const queryStringParams = this.parseQueryParms();
const { isAuthorized, clientData, decryptedParams } = await this.validateClientTagOnEntry(queryStringParams);
this.unauthorized = !isAuthorized;
if (!isAuthorized) {
// Remove the loading animation if client tag validation fails so users can see the Unauthorized Access message.
showIssLoadingModal(false);
return;
}
try {
// Check cookie
const issCookie = getISSCookie();
if (issCookie !== null && issCookie.VehicleMake && issCookie.VehicleModel) {
const clientParentAccountNumber = clientData.parentAccountNumber;
const cookieParentAccountNumber = issCookie.ReferralParentAccountNumber;
if (clientParentAccountNumber === cookieParentAccountNumber) {
const savedSessionTimeStamp = new Date(issCookie.SavedSessionTimeoutDate);
const isSavedSessionTimedOut = new Date(new Date().toUTCString()) > savedSessionTimeStamp;
if (!isSavedSessionTimedOut) {
this.mainStore.issConfig.enableContinueFromCookie = true;
}
}
} else {
updateOrCreateISSCookie(true);
}
} catch {
updateOrCreateISSCookie(true);
}
if (clientData.parameters?.length > 0) {
const finalParams = this.combineClientParameters(clientData.parameters, { ...queryStringParams, ...decryptedParams });
this.populateStoreItemsFromParams(finalParams);
}
} catch (e) {
global.$logger.logError('[Entry Page] Client Setup Error:', e);
this.unauthorized = true;
showIssLoadingModal(false);
return;
}
this.mainStore.applicationUser.coverageAttempts = 0;
// Forced full location redirect here. We do not want the entry page as part of the router/flow/path history.
window.location = `/?issPage=${issPageValues.WELCOME_PAGE}`;
},
methods:
{
navigateForward() {
// If we use navigateForward we need to skip saving session (creating referral).
this.$router.navigate(
this.navigationScenarios.MOVE_FORWARD_ENTRY_PAGE,
this.$route,
{},
{ [routerParams.SKIP_SAVE_SESSION]: true }
);
},
parseQueryParms() {
// Dump the query string parameters into an object
if (this.$route?.query) {
return Object.fromEntries(Object.entries(this.$route?.query).map(([key, value]) => [key.toLowerCase(), value]));
}
return {};
},
async validateClientTagOnEntry(queryStringParams) {
const clientTag = queryStringParams.clienttag;
if (!clientTag) {
return { isAuthorized: false };
}
// Set the client tag on the store here so we can use it for logging if need be.
this.mainStore.issConfig.clientTag = clientTag;
const resp = await validateISSClientTag(clientTag);
if (!resp) {
return { isAuthorized: false };
}
// Populate all the ISS Config values from the service call returns.
this.populateISSConfigValues(resp);
// Session should only be created / validated on successful client tag validation to avoid unnecessary sessions for unauthorized users.
await analyticsMixin.methods.validateSession();
let isAuthorized = false;
let clientData = null;
const decryptedParams = {};
const encryptedParametersPattern = this.mainStore.issConfig.encryptedParametersPattern;
if (resp.active && resp.accountName.length > 0) {
if (resp.authentication.startsWith('RSAToken')) {
const { token, signature } = queryStringParams;
const vsigResp = await validateISSClientSignature(clientTag, token, signature);
// Encrypted params only populated if the authentication type includes EncParams and we have a pattern to pull them out of the decrypted data.
// Try/Catch is here to ensure that any issues with populating these parameters does not impact the overall authentication/authorization of the client.
// They can fallback to manually entering the data on the webpage.
if (resp.authentication.includes('EncParams') && encryptedParametersPattern) {
try {
const encryptedParametersPatternRegex = RegExp(encryptedParametersPattern);
const match = vsigResp.decryptedData.match(encryptedParametersPatternRegex);
if ( match?.groups ) {
const params = match.groups;
for (const [key, value] of Object.entries(params)) {
decryptedParams[key.toLowerCase()] = value;
}
}
}
catch ( error ) {
global.$logger.logError(`[Entry Page] Unable to populate encrypted parameters: ${error} - Client Tag: ${clientTag} - Token: ${token} - Signature: ${signature}`);
}
}
isAuthorized = vsigResp?.valid ?? false;
this.mainStore.issConfig.isAuthenticated = isAuthorized;
// Log the signature validation failure so we can monitor/alert on it.
if ( !isAuthorized ) {
global.$logger.logError(`[Entry Page] Client signature validation failed for Client Tag: ${clientTag} - Reason: ${vsigResp?.failureReason ?? ''} - Token: ${token} - Signature: ${signature}`);
}
} else {
isAuthorized = true;
}
if (isAuthorized) {
clientData = resp;
}
}
return { isAuthorized, clientData, decryptedParams };
},
populateISSConfigValues(data) {
this.mainStore.issConfig.clientName = data.accountName;
this.mainStore.issConfig.clientFullName = data.accountName; // Defaults to use the client name.
this.mainStore.issConfig.clientDisplayName = data.accountName; // Defaults to use the client name.
this.mainStore.issConfig.clientPossessiveName = toPossessive(data.accountName); // Defaults to use the client name.
this.mainStore.issConfig.parentAccountNumber = data.parentAccountNumber;
this.mainStore.issConfig.styleSheet = data.styleSheet;
this.mainStore.issConfig.isCoverageEnabled = data.coverageEnabled;
this.mainStore.issConfig.siteType = data.siteType;
if (data.clientFlags) {
const clientFlags = JSON.parse(data.clientFlags);
if (clientFlags.TPAEnabled) {
this.mainStore.issConfig.enableTPAFlow = true;
}
if (clientFlags.ClientFullName != null) {
this.mainStore.issConfig.clientFullName = clientFlags.ClientFullName;
}
if (clientFlags.ClientDisplayName != null) {
this.mainStore.issConfig.clientDisplayName = clientFlags.ClientDisplayName;
this.mainStore.issConfig.clientPossessiveName = toPossessive(clientFlags.ClientDisplayName);
}
if (clientFlags.ClientPossessiveName != null) {
this.mainStore.issConfig.clientPossessiveName = clientFlags.ClientPossessiveName;
}
if (clientFlags.ClaimRegistrationRequired) {
this.mainStore.issConfig.isClaimRegistrationRequired = true;
}
if (clientFlags.EnableNoCompQuote) {
this.mainStore.issConfig.enableNoCompQuote = true;
}
if ( clientFlags.EncryptedParametersPattern != null ) {
this.mainStore.issConfig.encryptedParametersPattern = clientFlags.EncryptedParametersPattern;
}
if (clientFlags.UseMemberNumber) {
this.mainStore.issConfig.useMemberNumber = true;
}
if (clientFlags.HiddenFields) {
if (clientFlags.HiddenFields.includes('PolicyNumber')) {
this.mainStore.issConfig.hiddenFields.policyNumber = true;
}
if (clientFlags.HiddenFields.includes('PhoneNumber')) {
this.mainStore.issConfig.hiddenFields.phoneNumber = true;
}
}
}
},
combineClientParameters(configParams, queryStringParams) {
const finalParams = {};
try {
const clientParams = JSON.parse(configParams);
for (const clientParam of clientParams) {
const paramName = clientParam.toLowerCase();
const value = queryStringParams[paramName];
if (value) {
finalParams[paramName] = value;
}
}
} catch (e) {
window.console.error(`Error combining client parameters: ${e}`);
}
return finalParams;
},
populateStoreItemsFromParams(params) {
// Populate store items from parameters.
for (const [key, value] of Object.entries(params)) {
switch (key.toLowerCase()) {
case 'policynbr':
case 'policynumber':
this.mainStore.order.policy.policyNumber = value;
this.mainStore.issConfig.disabledFields.policyNumber = true;
break;
case 'policyzipcode':
this.mainStore.order.policy.policyZipCode = value;
this.mainStore.issConfig.disabledFields.policyZipCode = true;
break;
case 'dateofloss':
case 'lossdate':
const formattedDate = this.formatToYYYYMMDD(value);
// Only set this if it formatted correctly.
if ( formattedDate ) {
this.mainStore.order.policy.dateOfLoss = formattedDate;
this.mainStore.issConfig.disabledFields.dateOfLoss = true;
}
break;
case 'returnurl':
case 'successreturnurl':
this.mainStore.issConfig.successReturnURL = value;
break;
case 'returnurl2':
case 'failurereturnurl':
this.mainStore.issConfig.failureReturnURL = value;
break;
// Not stored
case 'timestamp':
case 'token':
case 'signature':
break;
default:
}
}
},
formatToYYYYMMDD(dateString) {
try {
if (!dateString) {
return null;
}
// Avoid any UTC / local time issues by always treating the output as UTC.
const date = new Date(dateString);
if (Number.isNaN(date.getTime())) {
return null;
}
const year = date.getUTCFullYear();
const month = String(date.getUTCMonth() + 1).padStart(2, "0");
const day = String(date.getUTCDate()).padStart(2, "0");
return `${year}-${month}-${day}`;
} catch ( error ) {
global.$logger.logError(`[Entry Page] Error formatting date string: ${error} - Input: ${dateString}`);
return null;
}
}
}
};
</script>
<style lang="scss" scoped>
#message {
text-align: center;
}
</style>