Build and publish Docker images / Build and publish images (push) Successful in 2m35s
205 lines
5.9 KiB
Vue
205 lines
5.9 KiB
Vue
<script>
|
|
// utils and composables
|
|
import { login } from '../../api/auth';
|
|
import { useAlert } from 'dashboard/composables';
|
|
import { parseAPIErrorResponse } from 'dashboard/store/utils/api';
|
|
import { required, email } from '@vuelidate/validators';
|
|
import { useVuelidate } from '@vuelidate/core';
|
|
import { SESSION_STORAGE_KEYS } from 'dashboard/constants/sessionStorage';
|
|
import SessionStorage from 'shared/helpers/sessionStorage';
|
|
|
|
// components
|
|
import FormInput from '../../components/Form/Input.vue';
|
|
import Spinner from 'shared/components/Spinner.vue';
|
|
import NextButton from 'dashboard/components-next/button/Button.vue';
|
|
|
|
const IMPERSONATION_URL_SEARCH_KEY = 'impersonation';
|
|
const USER_NOT_CONFIRMED_ERROR_CODE = 'user_not_confirmed';
|
|
|
|
export default {
|
|
components: {
|
|
FormInput,
|
|
Spinner,
|
|
NextButton,
|
|
},
|
|
props: {
|
|
ssoAuthToken: { type: String, default: '' },
|
|
ssoAccountId: { type: String, default: '' },
|
|
ssoConversationId: { type: String, default: '' },
|
|
email: { type: String, default: '' },
|
|
authError: { type: String, default: '' },
|
|
},
|
|
setup() {
|
|
return {
|
|
v$: useVuelidate(),
|
|
};
|
|
},
|
|
data() {
|
|
return {
|
|
credentials: {
|
|
email: '',
|
|
password: '',
|
|
},
|
|
loginApi: {
|
|
message: '',
|
|
showLoading: false,
|
|
hasErrored: false,
|
|
},
|
|
error: '',
|
|
};
|
|
},
|
|
validations() {
|
|
return {
|
|
credentials: {
|
|
password: {
|
|
required,
|
|
},
|
|
email: {
|
|
required,
|
|
email,
|
|
},
|
|
},
|
|
};
|
|
},
|
|
created() {
|
|
if (this.ssoAuthToken) {
|
|
this.submitLogin();
|
|
}
|
|
if (this.authError) {
|
|
this.showAlertMessage(this.$t('LOGIN.API.UNAUTH'));
|
|
this.requestIdleCallbackPolyfill(() => {
|
|
const { query } = this.$route;
|
|
this.$router.replace({ query: { ...query, error: undefined } });
|
|
});
|
|
}
|
|
},
|
|
methods: {
|
|
requestIdleCallbackPolyfill(callback) {
|
|
if (window.requestIdleCallback) {
|
|
window.requestIdleCallback(callback);
|
|
} else {
|
|
setTimeout(callback, 0);
|
|
}
|
|
},
|
|
showAlertMessage(message) {
|
|
this.loginApi.showLoading = false;
|
|
this.loginApi.message = parseAPIErrorResponse(message);
|
|
useAlert(this.loginApi.message);
|
|
},
|
|
handleImpersonation() {
|
|
const urlParams = new URLSearchParams(window.location.search);
|
|
const impersonation = urlParams.get(IMPERSONATION_URL_SEARCH_KEY);
|
|
if (impersonation) {
|
|
SessionStorage.set(SESSION_STORAGE_KEYS.IMPERSONATION_USER, true);
|
|
}
|
|
},
|
|
submitLogin() {
|
|
this.loginApi.hasErrored = false;
|
|
this.loginApi.showLoading = true;
|
|
|
|
const credentials = {
|
|
email: this.email
|
|
? decodeURIComponent(this.email)
|
|
: this.credentials.email,
|
|
password: this.credentials.password,
|
|
sso_auth_token: this.ssoAuthToken,
|
|
ssoAccountId: this.ssoAccountId,
|
|
ssoConversationId: this.ssoConversationId,
|
|
};
|
|
|
|
login(credentials)
|
|
.then(() => {
|
|
this.handleImpersonation();
|
|
this.showAlertMessage(this.$t('LOGIN.API.SUCCESS_MESSAGE'));
|
|
})
|
|
.catch(response => {
|
|
if (response?.errorCode === USER_NOT_CONFIRMED_ERROR_CODE) {
|
|
this.loginApi.showLoading = false;
|
|
this.$router.push({
|
|
name: 'auth_verify_email',
|
|
state: { email: credentials.email },
|
|
});
|
|
return;
|
|
}
|
|
|
|
if (this.email) {
|
|
window.location = '/app/login';
|
|
}
|
|
this.loginApi.hasErrored = true;
|
|
let errorMessage = this.$t('LOGIN.API.ERROR_MESSAGE');
|
|
if (response?.response?.status === 401) {
|
|
errorMessage = this.$t('LOGIN.API.UNAUTH');
|
|
} else if (response) {
|
|
errorMessage = parseAPIErrorResponse(response);
|
|
}
|
|
this.showAlertMessage(errorMessage);
|
|
});
|
|
},
|
|
submitFormLogin() {
|
|
if (this.v$.credentials.email.$invalid && !this.email) {
|
|
this.showAlertMessage(this.$t('LOGIN.EMAIL.ERROR'));
|
|
return;
|
|
}
|
|
|
|
this.submitLogin();
|
|
},
|
|
},
|
|
};
|
|
</script>
|
|
|
|
<template>
|
|
<main
|
|
class="flex flex-col items-center justify-center w-full min-h-screen bg-n-brand/5 dark:bg-n-background sm:px-6 lg:px-8"
|
|
>
|
|
<!-- Regular Login Section -->
|
|
<section
|
|
class="bg-white shadow sm:mx-auto mb-8 mt-15 sm:w-full sm:max-w-lg dark:bg-n-solid-2 p-11 sm:shadow-lg sm:rounded-lg"
|
|
:class="{
|
|
'animate-wiggle': loginApi.hasErrored,
|
|
}"
|
|
>
|
|
<div v-if="!email">
|
|
<form class="space-y-5" @submit.prevent="submitFormLogin">
|
|
<FormInput
|
|
v-model="credentials.email"
|
|
name="email_address"
|
|
type="text"
|
|
data-testid="email_input"
|
|
:tabindex="1"
|
|
required
|
|
:label="$t('LOGIN.EMAIL.LABEL')"
|
|
:placeholder="$t('LOGIN.EMAIL.PLACEHOLDER')"
|
|
:has-error="v$.credentials.email.$error"
|
|
@input="v$.credentials.email.$touch"
|
|
/>
|
|
<FormInput
|
|
v-model="credentials.password"
|
|
type="password"
|
|
name="password"
|
|
data-testid="password_input"
|
|
required
|
|
:tabindex="2"
|
|
:label="$t('LOGIN.PASSWORD.LABEL')"
|
|
:placeholder="$t('LOGIN.PASSWORD.PLACEHOLDER')"
|
|
:has-error="v$.credentials.password.$error"
|
|
@input="v$.credentials.password.$touch"
|
|
/>
|
|
<NextButton
|
|
lg
|
|
type="submit"
|
|
data-testid="submit_button"
|
|
class="w-full"
|
|
:tabindex="3"
|
|
:label="$t('LOGIN.SUBMIT')"
|
|
:disabled="loginApi.showLoading"
|
|
:is-loading="loginApi.showLoading"
|
|
/>
|
|
</form>
|
|
</div>
|
|
<div v-else class="flex items-center justify-center">
|
|
<Spinner color-scheme="primary" size="" />
|
|
</div>
|
|
</section>
|
|
</main>
|
|
</template>
|