fix: SH admin dashboard setting and onboarding page cleanups (#5290)

Co-authored-by: jamesgeorge007 <25279263+jamesgeorge007@users.noreply.github.com>
This commit is contained in:
Nivedin 2025-07-29 20:59:39 +05:30 committed by GitHub
parent 56fa9534c7
commit 6597ade3f7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 367 additions and 281 deletions

View file

@ -27,7 +27,11 @@
@click="provider.action"
/>
<hr v-if="additionalLoginItems.length > 0" />
<hr
v-if="
additionalLoginItems.length > 0 && allowedAuthProviders.length
"
/>
<HoppSmartItem
v-for="loginItem in additionalLoginItems"
@ -58,7 +62,7 @@
</form>
<div
v-if="!allowedAuthProviders?.length"
v-if="!allowedAuthProviders?.length && !additionalLoginItems.length"
class="flex flex-col items-center text-center"
>
<p>{{ t("state.require_auth_provider") }}</p>

View file

@ -176,7 +176,8 @@
},
"onboarding": {
"add_atleast_one_auth_provider": "Please add at least one authentication provider to continue.",
"add_configurations": "Please add the configurations for the selected authentication methods.",
"add_configurations": "Add Configurations",
"add_configurations_description": "Please add the configurations for the selected authentication methods.",
"add_oauth_config": "Add Auth Configurations",
"auth_setup": "Authentication Setup",
"auth_successfully_configured": "authentication has been successfully configured.",
@ -214,7 +215,8 @@
"title": "SMTP"
},
"smtp_advanced_config_enable": "Enable to configure your own SMTP credentials",
"select_auth_provider": "Please select the authentication methods you want to set up.",
"select_auth_methods": "Please select authentications",
"select_auth_provider": "You can select one or more authentication providers to continue.",
"select_atleast_one": "Please select at least one authentication provider to continue.",
"start_onboarding": "Start Onboarding",
"welcome": "Welcome",

View file

@ -0,0 +1,46 @@
<template>
<div
class="flex flex-col justify-between space-y-2 p-5 w-56 h-46 cursor-pointer border-2 rounded-lg shadow transition bg-primaryLight border-primaryDark hover:border-accent"
:class="{
'!bg-primary !border-accentDark': selected,
}"
@click="$emit('click')"
>
<div class="flex flex-col space-y-2">
<div class="flex items-center justify-between">
<span class="text-[0.9rem] text-secondaryDark">
{{ t(title) }}
</span>
<icon-lucide-check
v-if="selected"
class="svg-icons h-4 w-4 text-accent"
/>
</div>
<span class="text-secondaryLight w-32">
{{ t(description) }}
</span>
</div>
<div>
<div class="flex items-center -space-x-2">
<slot />
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import IconLucideCheck from '~icons/lucide/check';
import { useI18n } from '~/composables/i18n';
defineProps<{
title: string;
description: string;
selected: boolean;
}>();
const emit = defineEmits(['click']);
const t = useI18n();
</script>

View file

@ -1,255 +1,185 @@
<template>
<div class="flex flex-col flex-1 py-8 p-4 justify-center w-full">
<div class="w-full max-w-screen-md mx-auto">
<div
v-if="isFirstTimeSetup && authConfigStep === 1"
class="py-8 rounded max-h-lg overflow-y-auto"
>
<div>
<h1 class="text-[1rem] font-normal">
{{ t('onboarding.select_auth_provider') }}
</h1>
<!-- auth providers -->
<div class="space-y-2 flex flex-col">
<div v-if="isFirstTimeSetup" class="flex max-w-xs space-x-3">
<span class="w-10 h-1 rounded-sm bg-accent"></span>
<span
class="w-10 h-1 rounded-sm bg-primaryDark"
:class="{
'!bg-accent': authConfigStep === 2,
}"
></span>
</div>
<div>
<div class="flex items-center space-x-4 my-8">
<div
class="flex flex-col space-y-2 p-5 h-40 cursor-pointer flex-1 border-2 bg-primaryLight rounded-lg border-primaryDark shadow hover:border-accent transition"
:class="{
'!bg-primary !border-accentDark':
selectedOptions.includes('OAuth'),
}"
@click="toggleSelectedOption('OAuth')"
>
<span class="text-[0.9rem] text-secondaryDark">
{{ t('onboarding.oauth.title') }}
</span>
<span class="text-secondaryLight h-10">
{{ t('onboarding.oauth.description') }}
</span>
<div class="my-4">
<div class="flex items-center -space-x-2">
<img
alt="user 1"
src="/assets/icons/auth/google.svg"
class="relative inline-block h-6 w-6 rounded-full border-2 border-primary object-cover object-center hover:z-10 focus:z-10"
/>
<img
alt="user 2"
src="/assets/icons/auth/github.svg"
class="relative inline-block h-6 w-6 rounded-full border-2 border-primary object-cover object-center hover:z-10 focus:z-10"
/>
<img
alt="user 3"
src="/assets/icons/auth/microsoft.svg"
class="relative inline-block h-6 w-6 rounded-full border-2 border-primary object-cover object-center hover:z-10 focus:z-10"
/>
</div>
</div>
</div>
<div
class="flex flex-col space-y-2 p-5 h-40 cursor-pointer flex-1 border-2 bg-primaryLight rounded-lg border-primaryDark shadow hover:border-accent transition"
:class="{
'!bg-primary !border-accentDark':
selectedOptions.includes('SMTP'),
}"
@click="toggleSelectedOption('SMTP')"
>
<span class="text-[0.9rem] text-secondaryDark">
{{ t('onboarding.smtp.title') }}
</span>
<span class="text-secondaryLight h-10">
{{ t('onboarding.smtp.description') }}
</span>
<div class="my-4">
<div class="flex items-center -space-x-2">
<img
alt="user 2"
src="/assets/icons/auth/email.svg"
class="relative inline-block h-6 w-6 rounded-full border-2 border-primary object-cover object-center hover:z-10 focus:z-10"
/>
</div>
</div>
</div>
</div>
<HoppButtonPrimary
:label="t('onboarding.add_oauth_config')"
@click="addAuthConfig"
:icon="IconLucideArrowRight"
:reverse="true"
class="mt-6"
/>
<div class="flex flex-col space-y-1 py-6">
<template v-if="authConfigStep === 1">
<h1 class="text-xl">{{ t('onboarding.select_auth_methods') }}</h1>
<h2 class="text-base font-normal text-secondaryLight">
{{ t('onboarding.select_auth_provider') }}
</h2>
</template>
<template v-else>
<h1 class="text-xl">{{ t('onboarding.add_configurations') }}</h1>
<h2 class="text-base font-normal text-secondaryLight">
{{ t('onboarding.add_configurations_description') }}
</h2>
</template>
</div>
</div>
<!-- Auth setup step 2 -->
<div v-else-if="authConfigStep === 2">
<button
v-if="isFirstTimeSetup"
class="items-center flex space-x-2 cursor-pointer mb-4 group"
@click="authConfigStep = 1"
>
<span class="group-hover:opacity-80 transition-opacity">
<IconLucideArrowLeft class="svg-icons" />
</span>
<span class="group-hover:opacity-80 transition-opacity">
{{ t('app.back') }}
</span>
</button>
<h2>
{{ t('onboarding.add_configurations') }}
</h2>
<div class="min-h-[50vh]">
<template v-if="isFirstTimeSetup && authConfigStep === 1">
<div class="rounded max-h-lg">
<div class="flex items-center gap-4 mb-8 flex-wrap">
<AuthProviderCard
title="onboarding.oauth.title"
description="onboarding.oauth.description"
:selected="isSelected('OAUTH') && isOAuthEnabled"
@click="toggleSelectedOption('OAUTH')"
>
<img
alt="user 1"
src="/assets/icons/auth/google.svg"
class="relative inline-block h-6 w-6 rounded-full border-2 border-primary object-cover object-center hover:z-10 focus:z-10"
/>
<img
alt="user 2"
src="/assets/icons/auth/github.svg"
class="relative inline-block h-6 w-6 rounded-full border-2 border-primary object-cover object-center hover:z-10 focus:z-10"
/>
<img
alt="user 3"
src="/assets/icons/auth/microsoft.svg"
class="relative inline-block h-6 w-6 rounded-full border-2 border-primary object-cover object-center hover:z-10 focus:z-10"
/>
</AuthProviderCard>
<div class="my-5 overflow-y-auto max-h-[60vh]">
<div
id="accordion-nested-parent"
data-accordion="collapse"
class="space-y-4"
>
<AuthProviderCard
title="onboarding.smtp.title"
description="onboarding.smtp.description"
:selected="isSelected('SMTP')"
@click="toggleSelectedOption('SMTP')"
>
<img
alt="user 2"
src="/assets/icons/auth/email.svg"
class="relative inline-block h-6 w-6 rounded-full border-2 border-primary object-cover object-center hover:z-10 focus:z-10"
/>
</AuthProviderCard>
</div>
<HoppButtonPrimary
:label="t('onboarding.add_oauth_config')"
@click="proceedToConfig"
:icon="IconLucideArrowRight"
:reverse="true"
class="mt-6"
/>
</div>
</template>
<!-- configure selected providers -->
<template v-else-if="authConfigStep === 2">
<div class="my-5 overflow-y-auto max-h-[60vh] space-y-4">
<UiAccordion
v-if="selectedOptions.includes('OAuth')"
:initial-open="isOAuthEnabled"
v-if="isSelected('OAUTH')"
:initial-open="isOAuthEnabled || isSelected('OAUTH')"
title="onboarding.oauth.title"
description="onboarding.oauth.description_accordian"
@toggle="toggleConfig('OAUTH')"
class="bg-primary rounded-lg border-primaryDark shadow p-4 border flex flex-col"
>
<template v-slot:header="{ isOpen, toggleAccordion }">
<div class="w-full">
<div class="flex items-center justify-between flex-1 mb-2">
<span class="font-semibold text-[0.8rem]"
>{{ t('onboarding.oauth.title') }}
</span>
<span>
<HoppSmartToggle
:on="isOpen"
@change="
() => {
toggleAccordion();
toggleConfig('OAUTH');
}
"
class="ml-2"
/>
</span>
</div>
<span class="text-tiny text-secondaryLight">
{{ t('onboarding.oauth.description_accordian') }}
</span>
</div>
</template>
<template v-slot:content>
<OAuthSetup
v-model:currentConfigs="currentConfigs"
v-model:enabledConfigs="enabledConfigs"
@toggleConfig="toggleConfig"
/>
</template>
<OAuthSetup
v-model:currentConfigs="currentConfigs"
v-model:enabledConfigs="enabledConfigs"
@toggleConfig="toggleConfig"
/>
</UiAccordion>
<UiAccordion
v-if="selectedOptions.includes('SMTP')"
:initial-open="enabledConfigs.includes('MAILER')"
v-if="isSelected('SMTP')"
:initial-open="isSmtpEnabled"
title="onboarding.smtp.title"
description="onboarding.smtp.description_accordian"
@toggle="
() => {
toggleConfig('EMAIL');
toggleSmtpConfig();
}
"
class="bg-primary rounded-lg border-primaryDark shadow p-4 border flex flex-col"
>
<template v-slot:header="{ isOpen, toggleAccordion }">
<div class="w-full">
<div class="flex items-center justify-between flex-1 mb-2">
<span class="font-semibold text-[0.8rem]">
{{ t('onboarding.smtp.title') }}
</span>
<span>
<HoppSmartToggle
:on="isOpen"
@change="
() => {
toggleAccordion();
toggleConfig('EMAIL');
toggleSmtpConfig();
}
"
class="ml-2"
/>
</span>
</div>
<p class="text-secondaryLight text-tiny">
{{ t('onboarding.smtp.description_accordian') }}
</p>
</div>
</template>
<template v-slot:content>
<SmtpSetup
v-model:currentConfigs="currentConfigs"
v-model:enabledConfigs="enabledConfigs"
/>
</template>
<SmtpSetup
v-model:currentConfigs="currentConfigs"
v-model:enabledConfigs="enabledConfigs"
/>
</UiAccordion>
</div>
</div>
<HoppButtonPrimary
:label="t('onboarding.save_auth_config')"
@click="addOnboardingConfigs"
:reverse="true"
:icon="IconLucideSave"
:loading="submittingConfigs"
class="mt-4"
/>
<div class="flex items-center space-x-4 mt-6">
<HoppButtonSecondary
v-if="isFirstTimeSetup && authConfigStep === 2"
:label="t('app.back')"
@click="
() => {
authConfigStep = 1;
selectedOptions = [];
enabledConfigs = [];
}
"
:reverse="true"
:icon="IconLucideArrowLeft"
:loading="submittingConfigs"
:outline="true"
/>
<HoppButtonPrimary
:label="t('onboarding.save_auth_config')"
@click="submitConfigs"
:reverse="true"
:icon="IconLucideSave"
:loading="submittingConfigs"
/>
</div>
</template>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import { onMounted, ref, watch } from 'vue';
import { ref, watch, onMounted, computed } from 'vue';
import { useToast } from '~/composables/toast';
import { useI18n } from '~/composables/i18n';
import {
useOnboardingConfigHandler,
OAuthProvider,
OnBoardingSummary,
useOnboardingConfigHandler,
} from '~/composables/useOnboardingConfigHandler';
import OAuthSetup from './OAuthSetup.vue';
import SmtpSetup from './SmtpSetup.vue';
import IconLucideArrowRight from '~icons/lucide/arrow-right';
import IconLucideArrowLeft from '~icons/lucide/arrow-left';
import IconLucideSave from '~icons/lucide/save';
import { useToast } from '~/composables/toast';
import { useI18n } from '~/composables/i18n';
import AuthProviderCard from './AuthProviderCard.vue';
const t = useI18n();
const toast = useToast();
const props = withDefaults(
defineProps<{
isFirstTimeSetup: boolean;
}>(),
{
isFirstTimeSetup: true,
}
);
const props = defineProps<{ isFirstTimeSetup?: boolean }>();
const emit = defineEmits<{
(
e: 'complete-onboarding',
payload: {
submittingConfigs: boolean;
summary: OnBoardingSummary;
}
payload: { submittingConfigs: boolean; summary: OnBoardingSummary }
): void;
}>();
type SelectedOption = 'OAUTH' | 'SMTP';
const authConfigStep = ref(1);
const selectedOptions = ref<Array<'OAuth' | 'SMTP' | ''>>([]);
watch(
() => props.isFirstTimeSetup,
(newValue) => {
if (!newValue) {
authConfigStep.value = 2; // Skip to step 2 if not first time setup
selectedOptions.value = ['OAuth', 'SMTP']; // Default to both options
} else {
authConfigStep.value = 1; // Reset to step 1 for first time setup
selectedOptions.value = []; // Reset selected options
}
},
{ immediate: true }
);
const selectedOptions = ref<SelectedOption[]>([]);
const {
currentConfigs,
@ -262,54 +192,88 @@ const {
toggleSmtpConfig,
} = useOnboardingConfigHandler();
const OAuthProviders: OAuthProvider[] = ['GOOGLE', 'GITHUB', 'MICROSOFT'];
const OAuthProviders: (OAuthProvider | 'OAUTH')[] = [
'GOOGLE',
'GITHUB',
'MICROSOFT',
'OAUTH',
];
const isOAuthEnabled = ref(false);
onMounted(() => {
// Check if any OAuth provider is enabled
isOAuthEnabled.value = OAuthProviders.some((provider) =>
enabledConfigs.value.includes(provider)
);
updateOAuthEnabled();
});
watch(isProvidersLoading, (loading) => {
if (!loading) updateOAuthEnabled();
});
watch(
isProvidersLoading,
(isLoading) => {
if (!isLoading) {
isOAuthEnabled.value = OAuthProviders.some((provider) =>
enabledConfigs.value.includes(provider)
);
() => enabledConfigs.value,
(configs) => {
isOAuthEnabled.value = OAuthProviders.some((provider) =>
configs.includes(provider)
);
},
{ immediate: true }
);
watch(
() => props.isFirstTimeSetup,
(initialSetup) => {
if (initialSetup) {
authConfigStep.value = 1;
selectedOptions.value = [];
} else {
authConfigStep.value = 2;
selectedOptions.value = ['OAUTH', 'SMTP'];
}
},
{ immediate: true }
);
const addOnboardingConfigs = async () => {
const isSelected = (option: SelectedOption) =>
selectedOptions.value.includes(option as any);
const isSmtpEnabled = computed(() => enabledConfigs.value.includes('MAILER'));
const updateOAuthEnabled = () => {
isOAuthEnabled.value = OAuthProviders.some((provider) =>
enabledConfigs.value.includes(provider)
);
};
const toggleSelectedOption = (option: SelectedOption) => {
if (selectedOptions.value.includes(option as any)) {
selectedOptions.value = selectedOptions.value.filter(
(opt) => opt !== option
);
} else {
selectedOptions.value.push(option as any);
}
if (option === 'SMTP') {
toggleConfig('EMAIL');
toggleSmtpConfig();
} else {
toggleConfig(option);
}
};
const proceedToConfig = () => {
if (!selectedOptions.value.length) {
toast.error(t('onboarding.select_atleast_one'));
return;
}
authConfigStep.value = 2;
};
const submitConfigs = async () => {
const res = await addOnBoardingConfigs();
if (res && res.token) {
if (res?.token) {
emit('complete-onboarding', {
submittingConfigs: submittingConfigs.value,
summary: onBoardingSummary.value,
});
}
};
const toggleSelectedOption = (option: 'OAuth' | 'SMTP') => {
if (selectedOptions.value.includes(option)) {
selectedOptions.value = selectedOptions.value.filter(
(opt) => opt !== option
);
} else {
selectedOptions.value.push(option);
}
};
const addAuthConfig = () => {
if (selectedOptions.value.length === 0) {
toast.error(t('onboarding.select_atleast_one'));
return;
}
authConfigStep.value = 2;
};
</script>

View file

@ -13,10 +13,10 @@
<icon-lucide-badge-check class="svg-icons text-green-500 !h-8 !w-8" />
</span>
</h1>
<h2>
<h2 class="text-base">
{{ t('onboarding.setup_complete.description') }}
<br />
<span class="text-secondaryLight text-tiny">
<span class="text-secondaryLight text-[0.9rem]">
{{ t('onboarding.setup_complete.description_sub') }}
</span>
</h2>

View file

@ -5,6 +5,7 @@
<HoppSmartInput
v-model="currentConfigs.mailerConfigs[smtp.ADDRESS_FROM.id]"
:label="smtp.ADDRESS_FROM.text"
:autofocus="false"
input-styles="floating-input"
class="!my-2 !bg-primaryLight flex-1"
/>
@ -12,6 +13,7 @@
v-if="smtp.SMTP_URL.enabled"
v-model="currentConfigs.mailerConfigs[smtp.SMTP_URL.id]"
:label="smtp.SMTP_URL.text"
:autofocus="false"
input-styles="floating-input"
class="!my-2 !bg-primaryLight flex-1"
/>

View file

@ -33,7 +33,6 @@
placeholder="e.g., 60 (in seconds)"
:autofocus="false"
class="!my-2 !bg-primaryLight flex-1"
type="number"
@update:model-value="
validateNumberValue(rateLimitConfig.fields.rate_limit_ttl)
"
@ -46,7 +45,6 @@
placeholder="e.g., 100 (requests per TTL)"
:autofocus="false"
class="!my-2 !bg-primaryLight flex-1"
type="number"
@update:model-value="
validateNumberValue(rateLimitConfig.fields.rate_limit_max)
"

View file

@ -1,43 +1,77 @@
<template>
<div>
<section class="w-full">
<div
class="flex items-center space-x-3"
class="flex items-center justify-between w-full space-x-3"
:aria-expanded="isOpen"
:aria-controls="UID"
:aria-controls="contentId"
>
<slot
name="header"
:is-open="isOpen"
:toggle-accordion="toggleAccordion"
/>
<slot name="header" :is-open="isOpen" :toggle-accordion="toggleAccordion">
<div class="flex flex-col text-left w-full">
<div class="flex items-center justify-between mb-1">
<span class="font-semibold text-[0.8rem]">
{{ t(title || '') }}
</span>
<HoppSmartToggle
:on="isOpen"
@change="toggleAccordion"
class="ml-2"
/>
</div>
<span class="text-tiny text-secondaryLight">
{{ t(description || '') }}
</span>
</div>
</slot>
</div>
<div v-show="isOpen" :aria-labelledby="UID" :id="UID">
<slot name="content" />
<div
v-show="isOpen"
:id="contentId"
role="region"
:aria-labelledby="headerId"
class="transition-all duration-300 ease-in-out"
>
<slot name="content">
<div class="mt-2">
<slot />
</div>
</slot>
</div>
</div>
</section>
</template>
<script lang="ts" setup>
import { ref, watch } from 'vue';
import { useI18n } from '~/composables/i18n';
const UID = 'accordion-' + Math.random().toString(36).substr(2, 9);
const t = useI18n();
const props = defineProps<{
initialOpen?: boolean;
title?: string; // Optional fallback title
description?: string; // Optional fallback description
}>();
const emit = defineEmits<{
(e: 'toggle', value: boolean): void;
}>();
const idSuffix = Math.random().toString(36).substring(2, 9);
const contentId = `accordion-content-${idSuffix}`;
const headerId = `accordion-header-${idSuffix}`;
const isOpen = ref(false);
watch(
() => props.initialOpen,
(newVal) => {
isOpen.value = newVal ?? false;
(val) => {
isOpen.value = val ?? false;
},
{ immediate: true }
);
const toggleAccordion = () => {
isOpen.value = !isOpen.value;
emit('toggle', isOpen.value);
};
</script>

View file

@ -197,6 +197,32 @@ export function useConfigHandler(updatedConfigs?: ServerConfigs) {
return field.trim() === '';
};
/**
* This is used to validate number fields, ensuring they are not NaN or less than or equal to zero.
* It checks if the field is a number or a numeric string, and returns true if it is not valid.
* @param field Field value to validate
* @returns Boolean indicating if the field is not valid
*/
const isNotValidNumber = (field: string | boolean | number) => {
if (typeof field === 'boolean') {
return false;
}
// Accept numbers or numeric strings (e.g., "1000"), but not non-numeric strings (e.g., "abc")
if (typeof field === 'number') {
return isNaN(field);
}
if (typeof field === 'string') {
// Trim and check if the string is a valid number
const trimmed = field.trim();
if (trimmed === '') return true;
return isNaN(Number(trimmed));
}
return true;
};
/**
* Check if the field is not valid
* This is used to validate number fields, ensuring they are not NaN or less than or equal to zero.
@ -227,27 +253,35 @@ export function useConfigHandler(updatedConfigs?: ServerConfigs) {
];
const hasSectionWithEmptyFields = sections.some((section) => {
if (
section.name === 'email' &&
!section.fields.mailer_use_custom_configs
) {
if (section.name === 'email') {
const { mailer_use_custom_configs, ...otherFields } = section.fields;
const excludeKeys = mailer_use_custom_configs
? ['mailer_smtp_url']
: [
'mailer_smtp_host',
'mailer_smtp_port',
'mailer_smtp_user',
'mailer_smtp_password',
];
return (
section.enabled &&
Object.entries(section.fields).some(
([key, value]) =>
isFieldEmpty(value) &&
key !== 'mailer_smtp_host' &&
key !== 'mailer_smtp_port' &&
key !== 'mailer_smtp_user' &&
key !== 'mailer_smtp_password'
Object.entries(otherFields).some(
([key, value]) => isFieldEmpty(value) && !excludeKeys.includes(key)
)
);
}
// This section has no enabled property, so we check fields directly
// eg: tokenConfigs, rateLimitConfigs
if (!('enabled' in section))
Object.values(section.fields).some(isFieldNotValid);
// for a valid number (>0) or non-empty string
if (section.name === 'token')
return Object.values(section.fields).some(isFieldNotValid);
// For rate limit section, we want to check if the values are not valid numbers
// and not empty strings
if (section.name === 'rate_limit')
return Object.values(section.fields).some(isNotValidNumber);
return (
section.enabled && Object.values(section.fields).some(isFieldEmpty)

View file

@ -7,7 +7,7 @@ import { getLocalConfig, setLocalConfig } from '~/helpers/localpersistence';
import { makeReadableKey } from '~/helpers/utils/readableKey';
export type OAuthProvider = 'GOOGLE' | 'GITHUB' | 'MICROSOFT';
export type EnabledConfig = OAuthProvider | 'MAILER' | 'EMAIL';
export type EnabledConfig = OAuthProvider | 'OAUTH' | 'MAILER' | 'EMAIL';
// common OAuth keys used across providers
type OAuthKeys = 'CLIENT_ID' | 'CLIENT_SECRET' | 'CALLBACK_URL' | 'SCOPE';
@ -132,7 +132,6 @@ export function useOnboardingConfigHandler() {
enabledConfigs.value = enabledConfigs.value.filter(
(c) => !['GOOGLE', 'GITHUB', 'MICROSOFT'].includes(c)
);
return;
}
if (key === 'EMAIL') {
@ -292,11 +291,14 @@ export function useOnboardingConfigHandler() {
return;
}
const filteredEnabledConfigs = enabledConfigs.value.filter(
(config) => config !== 'OAUTH' && config !== 'MAILER'
);
const configWithAuth = {
...validated,
[InfraConfigEnum.ViteAllowedAuthProviders]: enabledConfigs.value
.filter((x) => x !== 'MAILER')
.join(','),
[InfraConfigEnum.ViteAllowedAuthProviders]:
filteredEnabledConfigs.join(','),
};
try {