Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
131 changes: 131 additions & 0 deletions src/components/ForgotPasswordModal.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
<template>
<ion-header>
<ion-toolbar>
<ion-buttons slot="start">
<ion-button @click="closeModal">
<ion-icon slot="icon-only" :icon="closeOutline" />
</ion-button>
</ion-buttons>
<ion-title>{{$t("Reset password")}}</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<ion-item lines="full">
<ion-input @ionFocus="clearMessages" :label="$t('Username')" name="username" v-model="username" id="username" type="text" />
</ion-item>
<ion-text color="danger" v-if="errorMessage">
<p class="ion-padding-start">{{ errorMessage }}</p>
</ion-text>
<ion-text color="success" v-if="successMessage">
<p class="ion-padding-start">{{ successMessage }}</p>
</ion-text>

<ion-item lines="none" class="ion-margin-vertical ion-padding-vertical">
<ion-icon :icon="informationOutline" size="medium" slot="start"></ion-icon>
<ion-label >{{ $t("Your username must have an email already associated with it in HotWax to receive a reset password email. If you do not have an email linked to your account already, please contact your administrator to manually reset your password.") }}</ion-label>
</ion-item>

<ion-fab vertical="bottom" horizontal="end" slot="fixed">
<ion-fab-button @click="forgotPassword">
<ion-icon :icon="sendOutline" />
</ion-fab-button>
</ion-fab>
</ion-content>
</template>

<script lang="ts">
import { defineComponent } from 'vue';
import {
IonButton,
IonButtons,
IonContent,
IonHeader,
IonIcon,
IonTitle,
IonToolbar,
IonItem,
IonLabel,
IonFab,
IonFabButton,
modalController,
IonInput
} from '@ionic/vue';
import { closeOutline, informationOutline, sendOutline } from 'ionicons/icons';
import { UserService } from '@/services/UserService';
import { hasError } from '@hotwax/oms-api';
import { useRouter } from 'vue-router';
import { showToast } from '@/util';

export default defineComponent({
name:'ForgotPasswordModal',
components:{
IonButton,
IonButtons,
IonContent,
IonHeader,
IonIcon,
IonTitle,
IonToolbar,
IonItem,
IonLabel,
IonFab,
IonFabButton,
IonInput
},
data(){
return {
username:'',
errorMessage:'',
successMessage:''
}
},
methods:{
closeModal() {
modalController.dismiss({ dismissed: true });
},
clearMessages(){
this.errorMessage = ""
this.successMessage = ""
},
async forgotPassword() {
if (!this.username.trim()) {
this.errorMessage = this.$t('Username cannot be empty.');
this.successMessage = '';
return;
}

const params = {
userName: this.username,
};

try {
const resp = await UserService.forgotPassword(params);

if (!hasError(resp)) {
this.successMessage = this.$t(resp.data._EVENT_MESSAGE_);
this.errorMessage = '';
showToast(this.successMessage)
this.closeModal()
} else {
throw resp.data._ERROR_MESSAGE_;
}
} catch (err) {
this.errorMessage = this.$t(
'Failed to send password reset link, please try again or contact administrator.'
Comment thread
ymaheshwari1 marked this conversation as resolved.
);
this.successMessage = '';
console.error(err);

Check warning on line 117 in src/components/ForgotPasswordModal.vue

View workflow job for this annotation

GitHub Actions / call-workflow-in-another-repo / reusable_workflow_job (20.x)

Unexpected console statement

Check warning on line 117 in src/components/ForgotPasswordModal.vue

View workflow job for this annotation

GitHub Actions / call-workflow-in-another-repo / reusable_workflow_job (18.x)

Unexpected console statement
}
},
},
setup(){
const router = useRouter()
return {
closeOutline,
informationOutline,
sendOutline,
router
}
}
})
</script>
12 changes: 11 additions & 1 deletion src/locales/en.json
Original file line number Diff line number Diff line change
@@ -1,19 +1,29 @@
{
"Confirm Password": "Confirm Password",
"Failed to fetch user-profile, please try again": "Failed to fetch user-profile, please try again",
"Failed to reset password, please try again and follow the instructions for creating a new password.": "Failed to reset password, please try again and follow the instructions for creating a new password.",
"Failed to send password reset link, please try again or contact administrator.": "Failed to send password reset link, please try again or contact administrator.",
"Finish resetting your password": "Finish resetting your password",
"Launch Pad": "Launch Pad",
"Login": "Login",
"Logout": "Logout",
"Logging out...": "Logging out...",
"New Password": "New Password",
"Next": "Next",
"Not configured": "Not configured",
"OMS": "OMS",
"Password": "Password",
"Reset Password":"Reset Password",
"Please fill in the OMS": "Please fill in the OMS",
"Please fill in the user details": "Please fill in the user details",
"Processing": "Processing",
"Something went wrong while login. Please contact administrator.": "Something went wrong while login. Please contact administrator.",
"Sorry, your username or password is incorrect. Please try again.": "Sorry, your username or password is incorrect. Please try again.",
"This application is not enabled for your account": "This application is not enabled for your account",
"Username": "Username",
"View profile": "View profile"
"Username cannot be empty.": "Username cannot be empty.",
"View profile": "View profile",
"Your password has been successfully reset.": "Your password has been successfully reset.",
"Your request for reset password has been processed. Please check your email, for further instructions.":"Your request for reset password has been processed. Please check your email, for further instructions.",
"Your username must have an email already associated with it in HotWax to receive a reset password email. If you do not have an email linked to your account already, please contact your administrator to manually reset your password.":"Your username must have an email already associated with it in HotWax to receive a reset password email. If you do not have an email linked to your account already, please contact your administrator to manually reset your password."
}
27 changes: 26 additions & 1 deletion src/router/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { RouteRecordRaw } from 'vue-router';
import Home from '@/views/Home.vue';
import Login from '@/views/Login.vue';
import { useAuthStore } from "@/store/auth";
import ResetPassword from '@/views/ResetPassword.vue';

const loginGuard = (to: any, from: any, next: any) => {
const authStore = useAuthStore()
Expand All @@ -12,6 +13,23 @@ const loginGuard = (to: any, from: any, next: any) => {
next();
};

const authGuard = async (to: any, from: any, next: any) => {
const authStore = useAuthStore()
if (!authStore.isAuthenticated) {
next('/login')
}
next()
};

const resetGuard = async (to: any, from: any, next: any) => {
const authStore = useAuthStore()
if (authStore.requirePasswordChange) {
next('/resetPassword')
return;
}
next()
};

const routes: Array<RouteRecordRaw> = [
{
path: '/',
Expand All @@ -21,13 +39,20 @@ const routes: Array<RouteRecordRaw> = [
path: '/home',
name: 'Home',
component: Home,
beforeEnter: resetGuard
},
{
path: '/login',
name: 'Login',
component: Login,
beforeEnter: loginGuard
}
},
{
path: '/resetPassword',
name: 'ResetPassword',
component: ResetPassword,
beforeEnter: authGuard
},
];

const router = createRouter({
Expand Down
20 changes: 19 additions & 1 deletion src/services/UserService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,9 +130,27 @@ const getUserPermissions = async (payload: any, token: any): Promise<any> => {
}
}

const resetPassword = async(params: any) : Promise<any> => {
return api({
url: "service/resetPassword",
method: "POST",
data: params
})
}

const forgotPassword = async(params: any) : Promise<any> => {
return api({
url: "sendResetPasswordEmail",
method: "post",
data: params
})
}

export const UserService = {
getUserProfile,
checkLoginOptions,
login,
getUserPermissions
getUserPermissions,
resetPassword,
forgotPassword
}
3 changes: 3 additions & 0 deletions src/store/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
expiration: undefined
},
redirectUrl: '',
requirePasswordChange: false, // denotes if password change is required for the user
maargOms: '',
permissions: [] as any
}),
Expand Down Expand Up @@ -55,7 +56,7 @@
const resp = await UserService.login(username, password);
if (hasError(resp)) {
showToast(translate('Sorry, your username or password is incorrect. Please try again.'));
console.error("error", resp.data._ERROR_MESSAGE_);

Check warning on line 59 in src/store/auth.ts

View workflow job for this annotation

GitHub Actions / call-workflow-in-another-repo / reusable_workflow_job (20.x)

Unexpected console statement

Check warning on line 59 in src/store/auth.ts

View workflow job for this annotation

GitHub Actions / call-workflow-in-another-repo / reusable_workflow_job (18.x)

Unexpected console statement
return Promise.reject(new Error(resp.data._ERROR_MESSAGE_));
}

Expand All @@ -64,6 +65,8 @@
expiration: resp.data.expirationTime
}

this.requirePasswordChange = resp.data.requirePasswordChange

this.current = await UserService.getUserProfile(this.token.value);
updateToken(this.token.value)

Expand All @@ -87,7 +90,7 @@
// If any of the API call in try block has status code other than 2xx it will be handled in common catch block.
// TODO Check if handling of specific status codes is required.
showToast(translate('Something went wrong while login. Please contact administrator.'));
console.error("error: ", error);

Check warning on line 93 in src/store/auth.ts

View workflow job for this annotation

GitHub Actions / call-workflow-in-another-repo / reusable_workflow_job (20.x)

Unexpected console statement

Check warning on line 93 in src/store/auth.ts

View workflow job for this annotation

GitHub Actions / call-workflow-in-another-repo / reusable_workflow_job (18.x)

Unexpected console statement
return Promise.reject(new Error(error))
}
},
Expand Down Expand Up @@ -128,7 +131,7 @@
// If any of the API call in try block has status code other than 2xx it will be handled in common catch block.
// TODO Check if handling of specific status codes is required.
showToast(translate('Something went wrong while login. Please contact administrator.'));
console.error("error: ", error);

Check warning on line 134 in src/store/auth.ts

View workflow job for this annotation

GitHub Actions / call-workflow-in-another-repo / reusable_workflow_job (20.x)

Unexpected console statement

Check warning on line 134 in src/store/auth.ts

View workflow job for this annotation

GitHub Actions / call-workflow-in-another-repo / reusable_workflow_job (18.x)

Unexpected console statement
return Promise.reject(new Error(error))
}
},
Expand All @@ -149,7 +152,7 @@
// Added logic to remove the `//` from the resp as in case of get request we are having the extra characters and in case of post we are having 403
resp = JSON.parse(resp.startsWith('//') ? resp.replace('//', '') : resp)
} catch(err) {
console.error('Error parsing data', err)

Check warning on line 155 in src/store/auth.ts

View workflow job for this annotation

GitHub Actions / call-workflow-in-another-repo / reusable_workflow_job (20.x)

Unexpected console statement

Check warning on line 155 in src/store/auth.ts

View workflow job for this annotation

GitHub Actions / call-workflow-in-another-repo / reusable_workflow_job (18.x)

Unexpected console statement
}

if(resp?.logoutAuthType == 'SAML2SSO') {
Expand Down
52 changes: 46 additions & 6 deletions src/views/Login.vue
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,13 @@
<ion-icon v-else slot="end" :icon="arrowForwardOutline" />
</ion-button>
</div>
<ion-item v-show="errorMessage" lines="none" class="ion-item-banner ion-margin-vertical">
<ion-icon :icon="warningOutline" slot="start" color="danger" />
<ion-label>
{{ $t('The username or password you entered is incorrect. Please try again.') }}
<a href="#" @click.prevent="openForgotPasswordModal">{{ $t('forgot password') }}</a>
</ion-label>
</ion-item>
</section>
</form>
</div>
Expand All @@ -67,18 +74,20 @@
IonItem,
IonPage,
IonSpinner,
loadingController
loadingController,
modalController
} from "@ionic/vue";
import { defineComponent } from "vue";
import { useRouter } from "vue-router";
import { useAuthStore } from "@/store/auth";
import Logo from '@/components/Logo.vue';
import { arrowForwardOutline, gridOutline } from 'ionicons/icons'
import { arrowForwardOutline, gridOutline,warningOutline } from 'ionicons/icons'
import { UserService } from "@/services/UserService";
import { translate } from "@/i18n";
import { appInfo, isMaargLogin, isOmsWithMaarg, showToast } from "@/util";
import { hasError } from "@hotwax/oms-api";
import { Actions, hasPermission } from "@/authorization";
import ForgotPasswordModal from "@/components/ForgotPasswordModal.vue";

export default defineComponent({
name: "Login",
Expand Down Expand Up @@ -109,12 +118,16 @@
loader: null as any,
loginOption: {} as any,
isCheckingOms: false,
isLoggingIn: false
isLoggingIn: false,
errorMessage: '',
};
},
ionViewWillEnter() {
this.initialise()
},
ionViewWillLeave() {
this.errorMessage = ''
},
methods: {
async initialise() {
this.hideBackground = true
Expand Down Expand Up @@ -243,7 +256,7 @@
await this.authStore.setMaargInstance(resp.data.maargInstanceUrl)
}
} catch (error) {
console.error(error)

Check warning on line 259 in src/views/Login.vue

View workflow job for this annotation

GitHub Actions / call-workflow-in-another-repo / reusable_workflow_job (20.x)

Unexpected console statement

Check warning on line 259 in src/views/Login.vue

View workflow job for this annotation

GitHub Actions / call-workflow-in-another-repo / reusable_workflow_job (18.x)

Unexpected console statement
}
},
async login() {
Expand All @@ -256,6 +269,14 @@
this.isLoggingIn = true;
try {
await this.authStore.login(username.trim(), password)
// when password needs to be changed, redirecting the user to reset page
if(this.authStore.requirePasswordChange) {
this.username = ''
this.password = ''
this.router.push('/resetPassword');
Comment thread
ymaheshwari1 marked this conversation as resolved.
this.isLoggingIn = false
return
}
if (this.authStore.getRedirectUrl) {
this.generateRedirectionLink()
} else {
Expand All @@ -264,8 +285,9 @@
this.password = ''
this.router.push('/')
}
} catch (error) {
} catch (error:any) {
this.errorMessage = error
console.error(error)

Check warning on line 290 in src/views/Login.vue

View workflow job for this annotation

GitHub Actions / call-workflow-in-another-repo / reusable_workflow_job (20.x)

Unexpected console statement

Check warning on line 290 in src/views/Login.vue

View workflow job for this annotation

GitHub Actions / call-workflow-in-another-repo / reusable_workflow_job (18.x)

Unexpected console statement
}
this.isLoggingIn = false;
},
Expand Down Expand Up @@ -339,6 +361,16 @@

omsUrl = omsUrl ? omsUrl : this.authStore.oms.startsWith('http') ? this.authStore.oms.includes('/api') ? this.authStore.oms : `${this.authStore.oms}/api/` : this.authStore.oms
window.location.replace(`${url}?oms=${omsUrl}&token=${this.authStore.token.value}&expirationTime=${this.authStore.token.expiration}${omsRedirectionUrl ? '&omsRedirectionUrl=' + omsRedirectionUrl : ''}`)
},
async openForgotPasswordModal(){
const forgotPasswordModal = await modalController.create({
component:ForgotPasswordModal,
})
forgotPasswordModal.onDidDismiss()
this.errorMessage = ''
this.username = ''
this.password = ''
return forgotPasswordModal.present()
}
},
setup () {
Expand All @@ -348,7 +380,8 @@
arrowForwardOutline,
authStore,
gridOutline,
router
router,
warningOutline
};
}
});
Expand All @@ -364,5 +397,12 @@
align-items: center;
height: 100%;
}

.ion-item-banner {
--background:#ED576B1A;
--border-radius: 8px;
}
.ion-item-banner a {
display: block;
color: var(--ion-color-danger) ;
}
</style>
Loading
Loading