fix: show "Sync Now" and "Test Email" button even if UI config is disabled

This commit is contained in:
Elias Schneider
2025-02-14 13:32:01 +01:00
parent 2e66211b7f
commit 4d0fff821e
4 changed files with 175 additions and 161 deletions

View File

@@ -1,5 +1,4 @@
<script lang="ts"> <script lang="ts">
import { env } from '$env/dynamic/public';
import CollapsibleCard from '$lib/components/collapsible-card.svelte'; import CollapsibleCard from '$lib/components/collapsible-card.svelte';
import AppConfigService from '$lib/services/app-config-service'; import AppConfigService from '$lib/services/app-config-service';
import appConfigStore from '$lib/stores/application-configuration-store'; import appConfigStore from '$lib/stores/application-configuration-store';
@@ -14,7 +13,6 @@
let { data } = $props(); let { data } = $props();
let appConfig = $state(data.appConfig); let appConfig = $state(data.appConfig);
const uiConfigDisabled = env.PUBLIC_UI_CONFIG_DISABLED === 'true';
const appConfigService = new AppConfigService(); const appConfigService = new AppConfigService();
async function updateAppConfig(updatedAppConfig: Partial<AllAppConfig>) { async function updateAppConfig(updatedAppConfig: Partial<AllAppConfig>) {
@@ -57,28 +55,26 @@
<title>Application Configuration</title> <title>Application Configuration</title>
</svelte:head> </svelte:head>
<fieldset class="flex flex-col gap-5" disabled={uiConfigDisabled}> <CollapsibleCard id="application-configuration-general" title="General" defaultExpanded>
<CollapsibleCard id="application-configuration-general" title="General" defaultExpanded> <AppConfigGeneralForm {appConfig} callback={updateAppConfig} />
<AppConfigGeneralForm {appConfig} callback={updateAppConfig} /> </CollapsibleCard>
</CollapsibleCard>
<CollapsibleCard <CollapsibleCard
id="application-configuration-email" id="application-configuration-email"
title="Email" title="Email"
description="Enable email notifications to alert users when a login is detected from a new device or description="Enable email notifications to alert users when a login is detected from a new device or
location." location."
> >
<AppConfigEmailForm {appConfig} callback={updateAppConfig} /> <AppConfigEmailForm {appConfig} callback={updateAppConfig} />
</CollapsibleCard> </CollapsibleCard>
<CollapsibleCard <CollapsibleCard
id="application-configuration-ldap" id="application-configuration-ldap"
title="LDAP" title="LDAP"
description="Configure LDAP settings to sync users and groups from an LDAP server." description="Configure LDAP settings to sync users and groups from an LDAP server."
> >
<AppConfigLdapForm {appConfig} callback={updateAppConfig} /> <AppConfigLdapForm {appConfig} callback={updateAppConfig} />
</CollapsibleCard> </CollapsibleCard>
</fieldset>
<CollapsibleCard id="application-configuration-images" title="Images"> <CollapsibleCard id="application-configuration-images" title="Images">
<UpdateApplicationImages callback={updateImages} /> <UpdateApplicationImages callback={updateImages} />

View File

@@ -1,4 +1,5 @@
<script lang="ts"> <script lang="ts">
import { env } from '$env/dynamic/public';
import CheckboxWithLabel from '$lib/components/checkbox-with-label.svelte'; import CheckboxWithLabel from '$lib/components/checkbox-with-label.svelte';
import { openConfirmDialog } from '$lib/components/confirm-dialog'; import { openConfirmDialog } from '$lib/components/confirm-dialog';
import FormInput from '$lib/components/form-input.svelte'; import FormInput from '$lib/components/form-input.svelte';
@@ -18,6 +19,7 @@
} = $props(); } = $props();
const appConfigService = new AppConfigService(); const appConfigService = new AppConfigService();
const uiConfigDisabled = env.PUBLIC_UI_CONFIG_DISABLED === 'true';
let isSendingTestEmail = $state(false); let isSendingTestEmail = $state(false);
@@ -86,46 +88,47 @@
</script> </script>
<form onsubmit={onSubmit}> <form onsubmit={onSubmit}>
<h4 class="text-lg font-semibold">SMTP Configuration</h4> <fieldset disabled={uiConfigDisabled}>
<div class="mt-4 grid grid-cols-1 items-end gap-5 md:grid-cols-2"> <h4 class="text-lg font-semibold">SMTP Configuration</h4>
<FormInput label="SMTP Host" bind:input={$inputs.smtpHost} /> <div class="mt-4 grid grid-cols-1 items-end gap-5 md:grid-cols-2">
<FormInput label="SMTP Port" type="number" bind:input={$inputs.smtpPort} /> <FormInput label="SMTP Host" bind:input={$inputs.smtpHost} />
<FormInput label="SMTP User" bind:input={$inputs.smtpUser} /> <FormInput label="SMTP Port" type="number" bind:input={$inputs.smtpPort} />
<FormInput label="SMTP Password" type="password" bind:input={$inputs.smtpPassword} /> <FormInput label="SMTP User" bind:input={$inputs.smtpUser} />
<FormInput label="SMTP From" bind:input={$inputs.smtpFrom} /> <FormInput label="SMTP Password" type="password" bind:input={$inputs.smtpPassword} />
<CheckboxWithLabel <FormInput label="SMTP From" bind:input={$inputs.smtpFrom} />
id="tls" <CheckboxWithLabel
label="TLS" id="tls"
description="Enable TLS for the SMTP connection." label="TLS"
bind:checked={$inputs.smtpTls.value} description="Enable TLS for the SMTP connection."
/> bind:checked={$inputs.smtpTls.value}
<CheckboxWithLabel />
id="skip-cert-verify" <CheckboxWithLabel
label="Skip Certificate Verification" id="skip-cert-verify"
description="This can be useful for self-signed certificates." label="Skip Certificate Verification"
bind:checked={$inputs.smtpSkipCertVerify.value} description="This can be useful for self-signed certificates."
/> bind:checked={$inputs.smtpSkipCertVerify.value}
</div> />
<h4 class="mt-10 text-lg font-semibold">Enabled Emails</h4> </div>
<div class="mt-4 flex flex-col gap-5"> <h4 class="mt-10 text-lg font-semibold">Enabled Emails</h4>
<CheckboxWithLabel <div class="mt-4 flex flex-col gap-5">
id="email-login-notification" <CheckboxWithLabel
label="Email Login Notification" id="email-login-notification"
description="Send an email to the user when they log in from a new device." label="Email Login Notification"
bind:checked={$inputs.emailLoginNotificationEnabled.value} description="Send an email to the user when they log in from a new device."
/> bind:checked={$inputs.emailLoginNotificationEnabled.value}
<CheckboxWithLabel />
id="email-one-time-access" <CheckboxWithLabel
label="Email One Time Access" id="email-one-time-access"
description="Allows users to sign in with a link sent to their email. This reduces the security significantly as anyone with access to the user's email can gain entry." label="Email One Time Access"
bind:checked={$inputs.emailOneTimeAccessEnabled.value} description="Allows users to sign in with a link sent to their email. This reduces the security significantly as anyone with access to the user's email can gain entry."
/> bind:checked={$inputs.emailOneTimeAccessEnabled.value}
</div> />
</div>
</fieldset>
<div class="mt-8 flex flex-wrap justify-end gap-3"> <div class="mt-8 flex flex-wrap justify-end gap-3">
<Button isLoading={isSendingTestEmail} variant="secondary" onclick={onTestEmail} <Button isLoading={isSendingTestEmail} variant="secondary" onclick={onTestEmail}
>Send test email</Button >Send test email</Button
> >
<Button type="submit">Save</Button> <Button type="submit" disabled={uiConfigDisabled}>Save</Button>
</div> </div>
</form> </form>

View File

@@ -1,4 +1,5 @@
<script lang="ts"> <script lang="ts">
import { env } from '$env/dynamic/public';
import CheckboxWithLabel from '$lib/components/checkbox-with-label.svelte'; import CheckboxWithLabel from '$lib/components/checkbox-with-label.svelte';
import FormInput from '$lib/components/form-input.svelte'; import FormInput from '$lib/components/form-input.svelte';
import { Button } from '$lib/components/ui/button'; import { Button } from '$lib/components/ui/button';
@@ -15,6 +16,7 @@
callback: (appConfig: Partial<AllAppConfig>) => Promise<void>; callback: (appConfig: Partial<AllAppConfig>) => Promise<void>;
} = $props(); } = $props();
const uiConfigDisabled = env.PUBLIC_UI_CONFIG_DISABLED === 'true';
let isLoading = $state(false); let isLoading = $state(false);
const updatedAppConfig = { const updatedAppConfig = {
@@ -42,28 +44,30 @@
</script> </script>
<form onsubmit={onSubmit}> <form onsubmit={onSubmit}>
<div class="flex flex-col gap-5"> <fieldset class="flex flex-col gap-5" disabled={uiConfigDisabled}>
<FormInput label="Application Name" bind:input={$inputs.appName} /> <div class="flex flex-col gap-5">
<FormInput <FormInput label="Application Name" bind:input={$inputs.appName} />
label="Session Duration" <FormInput
type="number" label="Session Duration"
description="The duration of a session in minutes before the user has to sign in again." type="number"
bind:input={$inputs.sessionDuration} description="The duration of a session in minutes before the user has to sign in again."
/> bind:input={$inputs.sessionDuration}
<CheckboxWithLabel />
id="self-account-editing" <CheckboxWithLabel
label="Enable Self-Account Editing" id="self-account-editing"
description="Whether the users should be able to edit their own account details." label="Enable Self-Account Editing"
bind:checked={$inputs.allowOwnAccountEdit.value} description="Whether the users should be able to edit their own account details."
/> bind:checked={$inputs.allowOwnAccountEdit.value}
<CheckboxWithLabel />
id="emails-verified" <CheckboxWithLabel
label="Emails Verified" id="emails-verified"
description="Whether the user's email should be marked as verified for the OIDC clients." label="Emails Verified"
bind:checked={$inputs.emailsVerified.value} description="Whether the user's email should be marked as verified for the OIDC clients."
/> bind:checked={$inputs.emailsVerified.value}
</div> />
<div class="mt-5 flex justify-end"> </div>
<Button {isLoading} type="submit">Save</Button> <div class="mt-5 flex justify-end">
</div> <Button {isLoading} type="submit">Save</Button>
</div>
</fieldset>
</form> </form>

View File

@@ -1,4 +1,5 @@
<script lang="ts"> <script lang="ts">
import { env } from '$env/dynamic/public';
import CheckboxWithLabel from '$lib/components/checkbox-with-label.svelte'; import CheckboxWithLabel from '$lib/components/checkbox-with-label.svelte';
import FormInput from '$lib/components/form-input.svelte'; import FormInput from '$lib/components/form-input.svelte';
import { Button } from '$lib/components/ui/button'; import { Button } from '$lib/components/ui/button';
@@ -18,6 +19,7 @@
} = $props(); } = $props();
const appConfigService = new AppConfigService(); const appConfigService = new AppConfigService();
const uiConfigDisabled = env.PUBLIC_UI_CONFIG_DISABLED === 'true';
let ldapEnabled = $state(appConfig.ldapEnabled); let ldapEnabled = $state(appConfig.ldapEnabled);
let ldapSyncing = $state(false); let ldapSyncing = $state(false);
@@ -96,89 +98,98 @@
</script> </script>
<form onsubmit={onSubmit}> <form onsubmit={onSubmit}>
<h4 class="text-lg font-semibold">Client Configuration</h4> <fieldset disabled={uiConfigDisabled}>
<div class="mt-4 grid grid-cols-1 items-start gap-5 md:grid-cols-2"> <h4 class="text-lg font-semibold">Client Configuration</h4>
<FormInput label="LDAP URL" placeholder="ldap://example.com:389" bind:input={$inputs.ldapUrl} /> <div class="mt-4 grid grid-cols-1 items-start gap-5 md:grid-cols-2">
<FormInput <FormInput
label="LDAP Bind DN" label="LDAP URL"
placeholder="cn=people,dc=example,dc=com" placeholder="ldap://example.com:389"
bind:input={$inputs.ldapBindDn} bind:input={$inputs.ldapUrl}
/> />
<FormInput label="LDAP Bind Password" type="password" bind:input={$inputs.ldapBindPassword} /> <FormInput
<FormInput label="LDAP Base DN" placeholder="dc=example,dc=com" bind:input={$inputs.ldapBase} /> label="LDAP Bind DN"
<FormInput placeholder="cn=people,dc=example,dc=com"
label="User Search Filter" bind:input={$inputs.ldapBindDn}
description="The Search filter to use to search/sync users." />
placeholder="(objectClass=person)" <FormInput label="LDAP Bind Password" type="password" bind:input={$inputs.ldapBindPassword} />
bind:input={$inputs.ldapUserSearchFilter} <FormInput
/> label="LDAP Base DN"
<FormInput placeholder="dc=example,dc=com"
label="Groups Search Filter" bind:input={$inputs.ldapBase}
description="The Search filter to use to search/sync groups." />
placeholder="(objectClass=groupOfNames)" <FormInput
bind:input={$inputs.ldapUserGroupSearchFilter} label="User Search Filter"
/> description="The Search filter to use to search/sync users."
<CheckboxWithLabel placeholder="(objectClass=person)"
id="skip-cert-verify" bind:input={$inputs.ldapUserSearchFilter}
label="Skip Certificate Verification" />
description="This can be useful for self-signed certificates." <FormInput
bind:checked={$inputs.ldapSkipCertVerify.value} label="Groups Search Filter"
/> description="The Search filter to use to search/sync groups."
</div> placeholder="(objectClass=groupOfNames)"
<h4 class="mt-10 text-lg font-semibold">Attribute Mapping</h4> bind:input={$inputs.ldapUserGroupSearchFilter}
<div class="mt-4 grid grid-cols-1 items-end gap-5 md:grid-cols-2"> />
<FormInput <CheckboxWithLabel
label="User Unique Identifier Attribute" id="skip-cert-verify"
description="The value of this attribute should never change." label="Skip Certificate Verification"
placeholder="uuid" description="This can be useful for self-signed certificates."
bind:input={$inputs.ldapAttributeUserUniqueIdentifier} bind:checked={$inputs.ldapSkipCertVerify.value}
/> />
<FormInput </div>
label="Username Attribute" <h4 class="mt-10 text-lg font-semibold">Attribute Mapping</h4>
placeholder="uid" <div class="mt-4 grid grid-cols-1 items-end gap-5 md:grid-cols-2">
bind:input={$inputs.ldapAttributeUserUsername} <FormInput
/> label="User Unique Identifier Attribute"
<FormInput description="The value of this attribute should never change."
label="User Mail Attribute" placeholder="uuid"
placeholder="mail" bind:input={$inputs.ldapAttributeUserUniqueIdentifier}
bind:input={$inputs.ldapAttributeUserEmail} />
/> <FormInput
<FormInput label="Username Attribute"
label="User First Name Attribute" placeholder="uid"
placeholder="givenName" bind:input={$inputs.ldapAttributeUserUsername}
bind:input={$inputs.ldapAttributeUserFirstName} />
/> <FormInput
<FormInput label="User Mail Attribute"
label="User Last Name Attribute" placeholder="mail"
placeholder="sn" bind:input={$inputs.ldapAttributeUserEmail}
bind:input={$inputs.ldapAttributeUserLastName} />
/> <FormInput
<FormInput label="User First Name Attribute"
label="Group Unique Identifier Attribute" placeholder="givenName"
description="The value of this attribute should never change." bind:input={$inputs.ldapAttributeUserFirstName}
placeholder="uuid" />
bind:input={$inputs.ldapAttributeGroupUniqueIdentifier} <FormInput
/> label="User Last Name Attribute"
<FormInput placeholder="sn"
label="Group Name Attribute" bind:input={$inputs.ldapAttributeUserLastName}
placeholder="cn" />
bind:input={$inputs.ldapAttributeGroupName} <FormInput
/> label="Group Unique Identifier Attribute"
<FormInput description="The value of this attribute should never change."
label="Admin Group Name" placeholder="uuid"
description="Members of this group will have Admin Privileges in Pocket ID." bind:input={$inputs.ldapAttributeGroupUniqueIdentifier}
placeholder="_admin_group_name" />
bind:input={$inputs.ldapAttributeAdminGroup} <FormInput
/> label="Group Name Attribute"
</div> placeholder="cn"
bind:input={$inputs.ldapAttributeGroupName}
/>
<FormInput
label="Admin Group Name"
description="Members of this group will have Admin Privileges in Pocket ID."
placeholder="_admin_group_name"
bind:input={$inputs.ldapAttributeAdminGroup}
/>
</div>
</fieldset>
<div class="mt-8 flex flex-wrap justify-end gap-3"> <div class="mt-8 flex flex-wrap justify-end gap-3">
{#if ldapEnabled} {#if ldapEnabled}
<Button variant="secondary" onclick={onDisable}>Disable</Button> <Button variant="secondary" onclick={onDisable} disabled={uiConfigDisabled}>Disable</Button>
<Button variant="secondary" onclick={syncLdap} isLoading={ldapSyncing}>Sync now</Button> <Button variant="secondary" onclick={syncLdap} isLoading={ldapSyncing}>Sync now</Button>
<Button type="submit">Save</Button> <Button type="submit" disabled={uiConfigDisabled}>Save</Button>
{:else} {:else}
<Button onclick={onEnable}>Enable</Button> <Button onclick={onEnable} disabled={uiConfigDisabled}>Enable</Button>
{/if} {/if}
</div> </div>
</form> </form>