feat: SAML feedback changes [CW-5666] (#12511)

This commit is contained in:
Shivam Mishra
2025-09-24 16:07:07 +05:30
committed by GitHub
parent eadbddaa9f
commit d3cd647e49
18 changed files with 116 additions and 78 deletions

View File

@@ -5,6 +5,7 @@ import { mapGetters } from 'vuex';
import { useAlert } from 'dashboard/composables';
import { DEFAULT_REDIRECT_URL } from 'dashboard/constants/globals';
import VueHcaptcha from '@hcaptcha/vue3-hcaptcha';
import SimpleDivider from '../../../../../components/Divider/SimpleDivider.vue';
import FormInput from '../../../../../components/Form/Input.vue';
import NextButton from 'dashboard/components-next/button/Button.vue';
import { isValidPassword } from 'shared/helpers/Validators';
@@ -17,6 +18,7 @@ export default {
FormInput,
GoogleOAuthButton,
NextButton,
SimpleDivider,
VueHcaptcha,
},
setup() {
@@ -210,9 +212,17 @@ export default {
:is-loading="isSignupInProgress"
/>
</form>
<GoogleOAuthButton v-if="showGoogleOAuth" class="flex-col-reverse">
{{ $t('REGISTER.OAUTH.GOOGLE_SIGNUP') }}
</GoogleOAuthButton>
<div class="flex flex-col">
<SimpleDivider
v-if="showGoogleOAuth || showSamlLogin"
:label="$t('COMMON.OR')"
bg="bg-n-background"
class="uppercase"
/>
<GoogleOAuthButton v-if="showGoogleOAuth">
{{ $t('REGISTER.OAUTH.GOOGLE_SIGNUP') }}
</GoogleOAuthButton>
</div>
<p
class="text-sm mb-1 mt-5 text-n-slate-12 [&>a]:text-n-brand [&>a]:font-medium [&>a]:hover:brightness-110"
v-html="termsLink"

View File

@@ -11,6 +11,7 @@ import SessionStorage from 'shared/helpers/sessionStorage';
import { useBranding } from 'shared/composables/useBranding';
// components
import SimpleDivider from '../../components/Divider/SimpleDivider.vue';
import FormInput from '../../components/Form/Input.vue';
import GoogleOAuthButton from '../../components/GoogleOauth/Button.vue';
import Spinner from 'shared/components/Spinner.vue';
@@ -30,6 +31,7 @@ export default {
GoogleOAuthButton,
Spinner,
NextButton,
SimpleDivider,
MfaVerification,
},
props: {
@@ -253,7 +255,25 @@ export default {
}"
>
<div v-if="!email">
<GoogleOAuthButton v-if="showGoogleOAuth" />
<div class="flex flex-col">
<GoogleOAuthButton v-if="showGoogleOAuth" />
<div v-if="showSamlLogin" class="mt-4 text-center">
<router-link
to="/app/login/sso"
class="inline-flex justify-center w-full px-4 py-3 bg-n-background dark:bg-n-solid-3 rounded-md shadow-sm ring-1 ring-inset ring-n-container dark:ring-n-container focus:outline-offset-0 hover:bg-n-alpha-2 dark:hover:bg-n-alpha-2"
>
<span class="i-lucide-key h-6 text-n-slate-11" />
<span class="ml-2 text-base font-medium text-n-slate-12">
{{ $t('LOGIN.SAML.LABEL') }}
</span>
</router-link>
</div>
<SimpleDivider
v-if="showGoogleOAuth || showSamlLogin"
:label="$t('COMMON.OR')"
class="uppercase"
/>
</div>
<form class="space-y-5" @submit.prevent="submitFormLogin">
<FormInput
v-model="credentials.email"
@@ -305,13 +325,5 @@ export default {
<Spinner color-scheme="primary" size="" />
</div>
</section>
<div v-if="showSamlLogin" class="mt-6 text-center">
<router-link
to="/app/login/sso"
class="inline-flex items-center text-sm font-medium text-n-brand hover:text-n-brand-dark"
>
{{ $t('LOGIN.SAML.LABEL') }}
</router-link>
</div>
</main>
</template>

View File

@@ -1,14 +1,22 @@
<script setup>
import { ref, computed, onMounted } from 'vue';
import { ref, nextTick, computed, onMounted } from 'vue';
import { useStore } from 'vuex';
import { required, email } from '@vuelidate/validators';
import { useVuelidate } from '@vuelidate/core';
import { useI18n } from 'vue-i18n';
import { useAlert } from 'dashboard/composables';
// components
import FormInput from '../../components/Form/Input.vue';
import NextButton from 'dashboard/components-next/button/Button.vue';
const props = defineProps({
authError: {
type: String,
default: '',
},
});
const store = useStore();
const { t } = useI18n();
@@ -21,6 +29,16 @@ const loginApi = ref({
hasErrored: false,
});
const handleAuthError = () => {
if (!props.authError) {
return;
}
const translatedMessage = t('LOGIN.SAML.API.ERROR_MESSAGE');
useAlert(translatedMessage);
loginApi.value.hasErrored = true;
};
const validations = {
credentials: {
email: {
@@ -35,11 +53,13 @@ const v$ = useVuelidate(validations, { credentials });
const globalConfig = computed(() => store.getters['globalConfig/get']);
const csrfToken = ref('');
onMounted(() => {
onMounted(async () => {
csrfToken.value =
document
.querySelector('meta[name="csrf-token"]')
?.getAttribute('content') || '';
await nextTick(handleAuthError);
});
</script>
@@ -70,7 +90,6 @@ onMounted(() => {
}"
>
<form class="space-y-5" method="POST" action="/api/v1/auth/saml_login">
<input type="hidden" name="authenticity_token" :value="csrfToken" I />
<FormInput
v-model="credentials.email"
name="email"
@@ -82,6 +101,12 @@ onMounted(() => {
:has-error="v$.credentials.email.$error"
@input="v$.credentials.email.$touch"
/>
<input
type="hidden"
class="h-0"
name="authenticity_token"
:value="csrfToken"
/>
<NextButton
lg
type="submit"

View File

@@ -26,6 +26,9 @@ export default [
name: 'sso_login',
component: SamlLogin,
meta: { requireEnterprise: true },
props: route => ({
authError: route.query.error,
}),
},
{
path: frontendURL('auth/signup'),