diff --git a/src/locales/en.json b/src/locales/en.json index 851679e..bc0561d 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -1,19 +1,34 @@ { - "Failed to fetch user-profile, please try again": "Failed to fetch user-profile, please try again", + "Already active session": "Already active session", + "Confirm Password": "Confirm Password", + "Email": "Email", + "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.", + "Forgot Password?": "Forgot Password?", "Launch Pad": "Launch Pad", "Login": "Login", "Logout": "Logout", + "New Password": "New Password", + "Failed to fetch user-profile, please try again": "Failed to fetch user-profile, please try again", "Logging out...": "Logging out...", "Next": "Next", "Not configured": "Not configured", "OMS": "OMS", "Password": "Password", + "Passwords do not match. Please try again": "Passwords do not match. Please try again", "Please fill in the OMS": "Please fill in the OMS", "Please fill in the user details": "Please fill in the user details", "Processing": "Processing", + "Reset Password": "Reset Password", + "Resume": "Resume", + "Send Reset Link": "Send Reset Link", "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", + "There is an already active session on for. Do you want to resume it, or would you prefer to log in again?": "There is an already active session on {oms} for {partyName}. Do you want to resume it, or would you prefer to log in again?", "Username": "Username", + "Username or Email cannot be empty.": "Username or Email cannot be empty.", + "Your password should be at least 5 characters long, it should contain at least one number, one alphabet and one special character.": "Your password should be at least 5 characters long, it should contain at least one number, one alphabet and one special character.", + "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 {email}, for further instructions.", + "This application is not enabled for your account": "This application is not enabled for your account", "View profile": "View profile" } \ No newline at end of file diff --git a/src/router/index.ts b/src/router/index.ts index 2a5fe6c..043302c 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -3,6 +3,8 @@ 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'; +import ForgotPassword from '@/views/ForgotPassword.vue'; const loginGuard = (to: any, from: any, next: any) => { const authStore = useAuthStore() @@ -12,6 +14,34 @@ 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 forgotPassword = async (to: any, from: any, next: any) => { + const authStore = useAuthStore() + + if (from.path !== '/login' && authStore.isAuthenticated) { + next('/') + return; + } + next() + return; +}; + const routes: Array = [ { path: '/', @@ -21,12 +51,25 @@ const routes: Array = [ path: '/home', name: 'Home', component: Home, + beforeEnter: resetGuard }, { path: '/login', name: 'Login', component: Login, beforeEnter: loginGuard + }, + { + path: '/resetPassword', + name: 'ResetPassword', + component: ResetPassword, + beforeEnter: authGuard + }, + { + path: '/forgotPassword', + name: 'ForgotPassword', + component: ForgotPassword, + beforeEnter: forgotPassword } ]; diff --git a/src/services/UserService.ts b/src/services/UserService.ts index 26ad34e..9ffe43b 100644 --- a/src/services/UserService.ts +++ b/src/services/UserService.ts @@ -40,8 +40,26 @@ const checkLoginOptions = async (): Promise => { }); } +const resetPassword = async(params: any) : Promise => { + return api({ + url: "service/resetPassword", + method: "POST", + data: params + }) +} + +const forgotPassword = async(params: any) : Promise => { + return api({ + url: "/sendResetPasswordMail", + method: "post", + data: params + }) +} + export const UserService = { getUserProfile, checkLoginOptions, - login + forgotPassword, + login, + resetPassword } \ No newline at end of file diff --git a/src/store/auth.ts b/src/store/auth.ts index b5699cd..e302a38 100644 --- a/src/store/auth.ts +++ b/src/store/auth.ts @@ -15,6 +15,7 @@ export const useAuthStore = defineStore('authStore', { expiration: undefined }, redirectUrl: '', + requirePasswordChange: false, // denotes if password change is required for the user maargOms: '' }), getters: { @@ -47,7 +48,6 @@ export const useAuthStore = defineStore('authStore', { try { 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_); return Promise.reject(new Error(resp.data._ERROR_MESSAGE_)); } @@ -57,6 +57,8 @@ export const useAuthStore = defineStore('authStore', { expiration: resp.data.expirationTime } + this.requirePasswordChange = resp.data.requirePasswordChange + this.current = await UserService.getUserProfile(this.token.value); updateToken(this.token.value) // Handling case for warnings like password may expire in few days diff --git a/src/views/ForgotPassword.vue b/src/views/ForgotPassword.vue new file mode 100644 index 0000000..12bfc70 --- /dev/null +++ b/src/views/ForgotPassword.vue @@ -0,0 +1,150 @@ + + + + + diff --git a/src/views/Login.vue b/src/views/Login.vue index c498423..5584015 100644 --- a/src/views/Login.vue +++ b/src/views/Login.vue @@ -41,6 +41,12 @@ + +

{{ errorMessage }}

+ + +

{{ $t('Forgot Password?') }}

+
@@ -107,6 +113,7 @@ export default defineComponent({ isConfirmingForActiveSession: false, loader: null as any, loginOption: {} as any, + errorMessage: '', isCheckingOms: false, isLoggingIn: false }; @@ -114,6 +121,9 @@ export default defineComponent({ ionViewWillEnter() { this.initialise() }, + ionViewWillLeave() { + this.errorMessage = '' + }, methods: { async initialise() { this.hideBackground = true @@ -254,6 +264,15 @@ export default defineComponent({ 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'); + return + } + if (this.authStore.getRedirectUrl) { this.generateRedirectionLink() } else { @@ -262,7 +281,8 @@ export default defineComponent({ this.password = '' this.router.push('/') } - } catch (error) { + } catch (error: any) { + this.errorMessage = error console.error(error) } this.isLoggingIn = false; @@ -281,6 +301,9 @@ export default defineComponent({ console.error(error) } }, + forgotPassword() { + this.router.push('/forgotPassword') + }, async basicLogin() { try { const { oms, token, expirationTime } = this.$route.query as any diff --git a/src/views/ResetPassword.vue b/src/views/ResetPassword.vue new file mode 100644 index 0000000..a48ae83 --- /dev/null +++ b/src/views/ResetPassword.vue @@ -0,0 +1,156 @@ + + + + +