mirror of
				https://github.com/immich-app/immich.git
				synced 2025-10-30 18:35:00 -04:00 
			
		
		
		
	feat(web): combine auth settings (#9427)
This commit is contained in:
		
							parent
							
								
									844f5a16a1
								
							
						
					
					
						commit
						a05c990718
					
				| @ -0,0 +1,242 @@ | ||||
| <script lang="ts"> | ||||
|   import ConfirmDialogue from '$lib/components/shared-components/confirm-dialogue.svelte'; | ||||
|   import SettingAccordion from '$lib/components/shared-components/settings/setting-accordion.svelte'; | ||||
|   import SettingButtonsRow from '$lib/components/shared-components/settings/setting-buttons-row.svelte'; | ||||
|   import SettingInputField, { | ||||
|     SettingInputFieldType, | ||||
|   } from '$lib/components/shared-components/settings/setting-input-field.svelte'; | ||||
|   import SettingSwitch from '$lib/components/shared-components/settings/setting-switch.svelte'; | ||||
|   import { type SystemConfigDto } from '@immich/sdk'; | ||||
|   import { isEqual } from 'lodash-es'; | ||||
|   import { createEventDispatcher } from 'svelte'; | ||||
|   import { fade } from 'svelte/transition'; | ||||
|   import type { SettingsEventType } from '../admin-settings'; | ||||
| 
 | ||||
|   export let savedConfig: SystemConfigDto; | ||||
|   export let defaultConfig: SystemConfigDto; | ||||
|   export let config: SystemConfigDto; // this is the config that is being edited | ||||
|   export let disabled = false; | ||||
| 
 | ||||
|   const dispatch = createEventDispatcher<SettingsEventType>(); | ||||
| 
 | ||||
|   let isConfirmOpen = false; | ||||
| 
 | ||||
|   const handleToggleOverride = () => { | ||||
|     // click runs before bind | ||||
|     const previouslyEnabled = config.oauth.mobileOverrideEnabled; | ||||
|     if (!previouslyEnabled && !config.oauth.mobileRedirectUri) { | ||||
|       config.oauth.mobileRedirectUri = window.location.origin + '/api/oauth/mobile-redirect'; | ||||
|     } | ||||
|   }; | ||||
| 
 | ||||
|   const handleSave = (skipConfirm: boolean) => { | ||||
|     const allMethodsDisabled = !config.oauth.enabled && !config.passwordLogin.enabled; | ||||
|     if (allMethodsDisabled && !skipConfirm) { | ||||
|       isConfirmOpen = true; | ||||
|       return; | ||||
|     } | ||||
| 
 | ||||
|     isConfirmOpen = false; | ||||
|     dispatch('save', { passwordLogin: config.passwordLogin, oauth: config.oauth }); | ||||
|   }; | ||||
| </script> | ||||
| 
 | ||||
| {#if isConfirmOpen} | ||||
|   <ConfirmDialogue | ||||
|     id="disable-login-modal" | ||||
|     title="Disable login" | ||||
|     onClose={() => (isConfirmOpen = false)} | ||||
|     onConfirm={() => handleSave(true)} | ||||
|   > | ||||
|     <svelte:fragment slot="prompt"> | ||||
|       <div class="flex flex-col gap-4"> | ||||
|         <p>Are you sure you want to disable all login methods? Login will be completely disabled.</p> | ||||
|         <p> | ||||
|           To re-enable, use a | ||||
|           <a | ||||
|             href="https://immich.app/docs/administration/server-commands" | ||||
|             rel="noreferrer" | ||||
|             target="_blank" | ||||
|             class="underline" | ||||
|           > | ||||
|             Server Command</a | ||||
|           >. | ||||
|         </p> | ||||
|       </div> | ||||
|     </svelte:fragment> | ||||
|   </ConfirmDialogue> | ||||
| {/if} | ||||
| 
 | ||||
| <div> | ||||
|   <div in:fade={{ duration: 500 }}> | ||||
|     <form autocomplete="off" on:submit|preventDefault> | ||||
|       <div class="ml-4 mt-4 flex flex-col gap-4"> | ||||
|         <SettingAccordion key="oauth" title="OAuth" subtitle="Manage OAuth login settings"> | ||||
|           <div class="ml-4 mt-4 flex flex-col gap-4"> | ||||
|             <p class="text-sm dark:text-immich-dark-fg"> | ||||
|               For more details about this feature, refer to the <a | ||||
|                 href="https://immich.app/docs/administration/oauth" | ||||
|                 class="underline" | ||||
|                 target="_blank" | ||||
|                 rel="noreferrer">docs</a | ||||
|               >. | ||||
|             </p> | ||||
| 
 | ||||
|             <SettingSwitch | ||||
|               id="login-with-oauth" | ||||
|               {disabled} | ||||
|               title="ENABLE" | ||||
|               subtitle="Login with OAuth" | ||||
|               bind:checked={config.oauth.enabled} | ||||
|             /> | ||||
| 
 | ||||
|             {#if config.oauth.enabled} | ||||
|               <hr /> | ||||
|               <SettingInputField | ||||
|                 inputType={SettingInputFieldType.TEXT} | ||||
|                 label="ISSUER URL" | ||||
|                 bind:value={config.oauth.issuerUrl} | ||||
|                 required={true} | ||||
|                 disabled={disabled || !config.oauth.enabled} | ||||
|                 isEdited={!(config.oauth.issuerUrl == savedConfig.oauth.issuerUrl)} | ||||
|               /> | ||||
| 
 | ||||
|               <SettingInputField | ||||
|                 inputType={SettingInputFieldType.TEXT} | ||||
|                 label="CLIENT ID" | ||||
|                 bind:value={config.oauth.clientId} | ||||
|                 required={true} | ||||
|                 disabled={disabled || !config.oauth.enabled} | ||||
|                 isEdited={!(config.oauth.clientId == savedConfig.oauth.clientId)} | ||||
|               /> | ||||
| 
 | ||||
|               <SettingInputField | ||||
|                 inputType={SettingInputFieldType.TEXT} | ||||
|                 label="CLIENT SECRET" | ||||
|                 bind:value={config.oauth.clientSecret} | ||||
|                 required={true} | ||||
|                 disabled={disabled || !config.oauth.enabled} | ||||
|                 isEdited={!(config.oauth.clientSecret == savedConfig.oauth.clientSecret)} | ||||
|               /> | ||||
| 
 | ||||
|               <SettingInputField | ||||
|                 inputType={SettingInputFieldType.TEXT} | ||||
|                 label="SCOPE" | ||||
|                 bind:value={config.oauth.scope} | ||||
|                 required={true} | ||||
|                 disabled={disabled || !config.oauth.enabled} | ||||
|                 isEdited={!(config.oauth.scope == savedConfig.oauth.scope)} | ||||
|               /> | ||||
| 
 | ||||
|               <SettingInputField | ||||
|                 inputType={SettingInputFieldType.TEXT} | ||||
|                 label="SIGNING ALGORITHM" | ||||
|                 bind:value={config.oauth.signingAlgorithm} | ||||
|                 required={true} | ||||
|                 disabled={disabled || !config.oauth.enabled} | ||||
|                 isEdited={!(config.oauth.signingAlgorithm == savedConfig.oauth.signingAlgorithm)} | ||||
|               /> | ||||
| 
 | ||||
|               <SettingInputField | ||||
|                 inputType={SettingInputFieldType.TEXT} | ||||
|                 label="STORAGE LABEL CLAIM" | ||||
|                 desc="Automatically set the user's storage label to the value of this claim." | ||||
|                 bind:value={config.oauth.storageLabelClaim} | ||||
|                 required={true} | ||||
|                 disabled={disabled || !config.oauth.enabled} | ||||
|                 isEdited={!(config.oauth.storageLabelClaim == savedConfig.oauth.storageLabelClaim)} | ||||
|               /> | ||||
| 
 | ||||
|               <SettingInputField | ||||
|                 inputType={SettingInputFieldType.TEXT} | ||||
|                 label="STORAGE QUOTA CLAIM" | ||||
|                 desc="Automatically set the user's storage quota to the value of this claim." | ||||
|                 bind:value={config.oauth.storageQuotaClaim} | ||||
|                 required={true} | ||||
|                 disabled={disabled || !config.oauth.enabled} | ||||
|                 isEdited={!(config.oauth.storageQuotaClaim == savedConfig.oauth.storageQuotaClaim)} | ||||
|               /> | ||||
| 
 | ||||
|               <SettingInputField | ||||
|                 inputType={SettingInputFieldType.NUMBER} | ||||
|                 label="DEFAULT STORAGE QUOTA (GiB)" | ||||
|                 desc="Quota in GiB to be used when no claim is provided (Enter 0 for unlimited quota)." | ||||
|                 bind:value={config.oauth.defaultStorageQuota} | ||||
|                 required={true} | ||||
|                 disabled={disabled || !config.oauth.enabled} | ||||
|                 isEdited={!(config.oauth.defaultStorageQuota == savedConfig.oauth.defaultStorageQuota)} | ||||
|               /> | ||||
| 
 | ||||
|               <SettingInputField | ||||
|                 inputType={SettingInputFieldType.TEXT} | ||||
|                 label="BUTTON TEXT" | ||||
|                 bind:value={config.oauth.buttonText} | ||||
|                 required={false} | ||||
|                 disabled={disabled || !config.oauth.enabled} | ||||
|                 isEdited={!(config.oauth.buttonText == savedConfig.oauth.buttonText)} | ||||
|               /> | ||||
| 
 | ||||
|               <SettingSwitch | ||||
|                 id="auto-register-new-users" | ||||
|                 title="AUTO REGISTER" | ||||
|                 subtitle="Automatically register new users after signing in with OAuth" | ||||
|                 bind:checked={config.oauth.autoRegister} | ||||
|                 disabled={disabled || !config.oauth.enabled} | ||||
|               /> | ||||
| 
 | ||||
|               <SettingSwitch | ||||
|                 id="auto-launch-oauth" | ||||
|                 title="AUTO LAUNCH" | ||||
|                 subtitle="Start the OAuth login flow automatically upon navigating to the login page" | ||||
|                 disabled={disabled || !config.oauth.enabled} | ||||
|                 bind:checked={config.oauth.autoLaunch} | ||||
|               /> | ||||
| 
 | ||||
|               <SettingSwitch | ||||
|                 id="mobile-redirect-uri-override" | ||||
|                 title="MOBILE REDIRECT URI OVERRIDE" | ||||
|                 subtitle="Enable when 'app.immich:/' is an invalid redirect URI." | ||||
|                 disabled={disabled || !config.oauth.enabled} | ||||
|                 on:click={() => handleToggleOverride()} | ||||
|                 bind:checked={config.oauth.mobileOverrideEnabled} | ||||
|               /> | ||||
| 
 | ||||
|               {#if config.oauth.mobileOverrideEnabled} | ||||
|                 <SettingInputField | ||||
|                   inputType={SettingInputFieldType.TEXT} | ||||
|                   label="MOBILE REDIRECT URI" | ||||
|                   bind:value={config.oauth.mobileRedirectUri} | ||||
|                   required={true} | ||||
|                   disabled={disabled || !config.oauth.enabled} | ||||
|                   isEdited={!(config.oauth.mobileRedirectUri == savedConfig.oauth.mobileRedirectUri)} | ||||
|                 /> | ||||
|               {/if} | ||||
|             {/if} | ||||
|           </div> | ||||
|         </SettingAccordion> | ||||
| 
 | ||||
|         <SettingAccordion key="password" title="Password" subtitle="Manage password login settings"> | ||||
|           <div class="ml-4 mt-4 flex flex-col gap-4"> | ||||
|             <div class="ml-4 mt-4 flex flex-col"> | ||||
|               <SettingSwitch | ||||
|                 id="enable-password-login" | ||||
|                 title="ENABLED" | ||||
|                 {disabled} | ||||
|                 subtitle="Login with email and password" | ||||
|                 bind:checked={config.passwordLogin.enabled} | ||||
|               /> | ||||
|             </div> | ||||
|           </div> | ||||
|         </SettingAccordion> | ||||
| 
 | ||||
|         <SettingButtonsRow | ||||
|           showResetToDefault={!isEqual(savedConfig.passwordLogin, defaultConfig.passwordLogin) || | ||||
|             !isEqual(savedConfig.oauth, defaultConfig.oauth)} | ||||
|           {disabled} | ||||
|           on:reset={({ detail }) => dispatch('reset', { ...detail, configKeys: ['passwordLogin', 'oauth'] })} | ||||
|           on:save={() => handleSave(false)} | ||||
|         /> | ||||
|       </div> | ||||
|     </form> | ||||
|   </div> | ||||
| </div> | ||||
| @ -1,25 +0,0 @@ | ||||
| <script lang="ts"> | ||||
|   import ConfirmDialogue from '$lib/components/shared-components/confirm-dialogue.svelte'; | ||||
| 
 | ||||
|   export let onCancel: () => void; | ||||
|   export let onConfirm: () => void; | ||||
| </script> | ||||
| 
 | ||||
| <ConfirmDialogue id="disable-login-modal" title="Disable login" onClose={onCancel} {onConfirm}> | ||||
|   <svelte:fragment slot="prompt"> | ||||
|     <div class="flex flex-col gap-4"> | ||||
|       <p>Are you sure you want to disable all login methods? Login will be completely disabled.</p> | ||||
|       <p> | ||||
|         To re-enable, use a | ||||
|         <a | ||||
|           href="https://immich.app/docs/administration/server-commands" | ||||
|           rel="noreferrer" | ||||
|           target="_blank" | ||||
|           class="underline" | ||||
|         > | ||||
|           Server Command</a | ||||
|         >. | ||||
|       </p> | ||||
|     </div> | ||||
|   </svelte:fragment> | ||||
| </ConfirmDialogue> | ||||
| @ -1,213 +0,0 @@ | ||||
| <script lang="ts"> | ||||
|   import type { SystemConfigDto } from '@immich/sdk'; | ||||
|   import { isEqual } from 'lodash-es'; | ||||
|   import { createEventDispatcher } from 'svelte'; | ||||
|   import { fade } from 'svelte/transition'; | ||||
|   import type { SettingsEventType } from '../admin-settings'; | ||||
|   import ConfirmDisableLogin from '../confirm-disable-login.svelte'; | ||||
|   import SettingButtonsRow from '$lib/components/shared-components/settings/setting-buttons-row.svelte'; | ||||
|   import SettingInputField, { | ||||
|     SettingInputFieldType, | ||||
|   } from '$lib/components/shared-components/settings/setting-input-field.svelte'; | ||||
|   import SettingSwitch from '$lib/components/shared-components/settings/setting-switch.svelte'; | ||||
| 
 | ||||
|   export let savedConfig: SystemConfigDto; | ||||
|   export let defaultConfig: SystemConfigDto; | ||||
|   export let config: SystemConfigDto; // this is the config that is being edited | ||||
|   export let disabled = false; | ||||
| 
 | ||||
|   const dispatch = createEventDispatcher<SettingsEventType>(); | ||||
| 
 | ||||
|   const handleToggleOverride = () => { | ||||
|     // click runs before bind | ||||
|     const previouslyEnabled = config.oauth.mobileOverrideEnabled; | ||||
|     if (!previouslyEnabled && !config.oauth.mobileRedirectUri) { | ||||
|       config.oauth.mobileRedirectUri = window.location.origin + '/api/oauth/mobile-redirect'; | ||||
|     } | ||||
|   }; | ||||
| 
 | ||||
|   let isConfirmOpen = false; | ||||
|   let handleConfirm: (value: boolean) => void; | ||||
| 
 | ||||
|   const openConfirmModal = () => { | ||||
|     return new Promise((resolve) => { | ||||
|       handleConfirm = (value: boolean) => { | ||||
|         isConfirmOpen = false; | ||||
|         resolve(value); | ||||
|       }; | ||||
|       isConfirmOpen = true; | ||||
|     }); | ||||
|   }; | ||||
| 
 | ||||
|   const handleSave = async () => { | ||||
|     if (!savedConfig.passwordLogin.enabled && savedConfig.oauth.enabled && !config.oauth.enabled) { | ||||
|       const confirmed = await openConfirmModal(); | ||||
|       if (!confirmed) { | ||||
|         return; | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     if (!config.oauth.mobileOverrideEnabled) { | ||||
|       config.oauth.mobileRedirectUri = ''; | ||||
|     } | ||||
| 
 | ||||
|     dispatch('save', { oauth: config.oauth }); | ||||
|   }; | ||||
| </script> | ||||
| 
 | ||||
| {#if isConfirmOpen} | ||||
|   <ConfirmDisableLogin onCancel={() => handleConfirm(false)} onConfirm={() => handleConfirm(true)} /> | ||||
| {/if} | ||||
| 
 | ||||
| <div class="mt-2"> | ||||
|   <div in:fade={{ duration: 500 }}> | ||||
|     <form autocomplete="off" on:submit|preventDefault class="mx-4 flex flex-col gap-4 py-4"> | ||||
|       <p class="text-sm dark:text-immich-dark-fg"> | ||||
|         For more details about this feature, refer to the <a | ||||
|           href="https://immich.app/docs/administration/oauth" | ||||
|           class="underline" | ||||
|           target="_blank" | ||||
|           rel="noreferrer">docs</a | ||||
|         >. | ||||
|       </p> | ||||
| 
 | ||||
|       <SettingSwitch | ||||
|         id="login-with-oauth" | ||||
|         {disabled} | ||||
|         title="ENABLE" | ||||
|         subtitle="Login with OAuth" | ||||
|         bind:checked={config.oauth.enabled} | ||||
|       /> | ||||
| 
 | ||||
|       {#if config.oauth.enabled} | ||||
|         <hr /> | ||||
|         <SettingInputField | ||||
|           inputType={SettingInputFieldType.TEXT} | ||||
|           label="ISSUER URL" | ||||
|           bind:value={config.oauth.issuerUrl} | ||||
|           required={true} | ||||
|           disabled={disabled || !config.oauth.enabled} | ||||
|           isEdited={!(config.oauth.issuerUrl == savedConfig.oauth.issuerUrl)} | ||||
|         /> | ||||
| 
 | ||||
|         <SettingInputField | ||||
|           inputType={SettingInputFieldType.TEXT} | ||||
|           label="CLIENT ID" | ||||
|           bind:value={config.oauth.clientId} | ||||
|           required={true} | ||||
|           disabled={disabled || !config.oauth.enabled} | ||||
|           isEdited={!(config.oauth.clientId == savedConfig.oauth.clientId)} | ||||
|         /> | ||||
| 
 | ||||
|         <SettingInputField | ||||
|           inputType={SettingInputFieldType.TEXT} | ||||
|           label="CLIENT SECRET" | ||||
|           bind:value={config.oauth.clientSecret} | ||||
|           required={true} | ||||
|           disabled={disabled || !config.oauth.enabled} | ||||
|           isEdited={!(config.oauth.clientSecret == savedConfig.oauth.clientSecret)} | ||||
|         /> | ||||
| 
 | ||||
|         <SettingInputField | ||||
|           inputType={SettingInputFieldType.TEXT} | ||||
|           label="SCOPE" | ||||
|           bind:value={config.oauth.scope} | ||||
|           required={true} | ||||
|           disabled={disabled || !config.oauth.enabled} | ||||
|           isEdited={!(config.oauth.scope == savedConfig.oauth.scope)} | ||||
|         /> | ||||
| 
 | ||||
|         <SettingInputField | ||||
|           inputType={SettingInputFieldType.TEXT} | ||||
|           label="SIGNING ALGORITHM" | ||||
|           bind:value={config.oauth.signingAlgorithm} | ||||
|           required={true} | ||||
|           disabled={disabled || !config.oauth.enabled} | ||||
|           isEdited={!(config.oauth.signingAlgorithm == savedConfig.oauth.signingAlgorithm)} | ||||
|         /> | ||||
| 
 | ||||
|         <SettingInputField | ||||
|           inputType={SettingInputFieldType.TEXT} | ||||
|           label="STORAGE LABEL CLAIM" | ||||
|           desc="Automatically set the user's storage label to the value of this claim." | ||||
|           bind:value={config.oauth.storageLabelClaim} | ||||
|           required={true} | ||||
|           disabled={disabled || !config.oauth.enabled} | ||||
|           isEdited={!(config.oauth.storageLabelClaim == savedConfig.oauth.storageLabelClaim)} | ||||
|         /> | ||||
| 
 | ||||
|         <SettingInputField | ||||
|           inputType={SettingInputFieldType.TEXT} | ||||
|           label="STORAGE QUOTA CLAIM" | ||||
|           desc="Automatically set the user's storage quota to the value of this claim." | ||||
|           bind:value={config.oauth.storageQuotaClaim} | ||||
|           required={true} | ||||
|           disabled={disabled || !config.oauth.enabled} | ||||
|           isEdited={!(config.oauth.storageQuotaClaim == savedConfig.oauth.storageQuotaClaim)} | ||||
|         /> | ||||
| 
 | ||||
|         <SettingInputField | ||||
|           inputType={SettingInputFieldType.NUMBER} | ||||
|           label="DEFAULT STORAGE QUOTA (GiB)" | ||||
|           desc="Quota in GiB to be used when no claim is provided (Enter 0 for unlimited quota)." | ||||
|           bind:value={config.oauth.defaultStorageQuota} | ||||
|           required={true} | ||||
|           disabled={disabled || !config.oauth.enabled} | ||||
|           isEdited={!(config.oauth.defaultStorageQuota == savedConfig.oauth.defaultStorageQuota)} | ||||
|         /> | ||||
| 
 | ||||
|         <SettingInputField | ||||
|           inputType={SettingInputFieldType.TEXT} | ||||
|           label="BUTTON TEXT" | ||||
|           bind:value={config.oauth.buttonText} | ||||
|           required={false} | ||||
|           disabled={disabled || !config.oauth.enabled} | ||||
|           isEdited={!(config.oauth.buttonText == savedConfig.oauth.buttonText)} | ||||
|         /> | ||||
| 
 | ||||
|         <SettingSwitch | ||||
|           id="auto-register-new-users" | ||||
|           title="AUTO REGISTER" | ||||
|           subtitle="Automatically register new users after signing in with OAuth" | ||||
|           bind:checked={config.oauth.autoRegister} | ||||
|           disabled={disabled || !config.oauth.enabled} | ||||
|         /> | ||||
| 
 | ||||
|         <SettingSwitch | ||||
|           id="auto-launch-oauth" | ||||
|           title="AUTO LAUNCH" | ||||
|           subtitle="Start the OAuth login flow automatically upon navigating to the login page" | ||||
|           disabled={disabled || !config.oauth.enabled} | ||||
|           bind:checked={config.oauth.autoLaunch} | ||||
|         /> | ||||
| 
 | ||||
|         <SettingSwitch | ||||
|           id="mobile-redirect-uri-override" | ||||
|           title="MOBILE REDIRECT URI OVERRIDE" | ||||
|           subtitle="Enable when 'app.immich:/' is an invalid redirect URI." | ||||
|           disabled={disabled || !config.oauth.enabled} | ||||
|           on:click={() => handleToggleOverride()} | ||||
|           bind:checked={config.oauth.mobileOverrideEnabled} | ||||
|         /> | ||||
| 
 | ||||
|         {#if config.oauth.mobileOverrideEnabled} | ||||
|           <SettingInputField | ||||
|             inputType={SettingInputFieldType.TEXT} | ||||
|             label="MOBILE REDIRECT URI" | ||||
|             bind:value={config.oauth.mobileRedirectUri} | ||||
|             required={true} | ||||
|             disabled={disabled || !config.oauth.enabled} | ||||
|             isEdited={!(config.oauth.mobileRedirectUri == savedConfig.oauth.mobileRedirectUri)} | ||||
|           /> | ||||
|         {/if} | ||||
|       {/if} | ||||
| 
 | ||||
|       <SettingButtonsRow | ||||
|         on:reset={({ detail }) => dispatch('reset', { ...detail, configKeys: ['oauth'] })} | ||||
|         on:save={() => handleSave()} | ||||
|         showResetToDefault={!isEqual(savedConfig.oauth, defaultConfig.oauth)} | ||||
|         {disabled} | ||||
|       /> | ||||
|     </form> | ||||
|   </div> | ||||
| </div> | ||||
| @ -1,68 +0,0 @@ | ||||
| <script lang="ts"> | ||||
|   import type { SystemConfigDto } from '@immich/sdk'; | ||||
|   import { isEqual } from 'lodash-es'; | ||||
|   import { createEventDispatcher } from 'svelte'; | ||||
|   import { fade } from 'svelte/transition'; | ||||
|   import type { SettingsEventType } from '../admin-settings'; | ||||
|   import ConfirmDisableLogin from '../confirm-disable-login.svelte'; | ||||
|   import SettingButtonsRow from '$lib/components/shared-components/settings/setting-buttons-row.svelte'; | ||||
|   import SettingSwitch from '$lib/components/shared-components/settings/setting-switch.svelte'; | ||||
| 
 | ||||
|   export let savedConfig: SystemConfigDto; | ||||
|   export let defaultConfig: SystemConfigDto; | ||||
|   export let config: SystemConfigDto; // this is the config that is being edited | ||||
|   export let disabled = false; | ||||
| 
 | ||||
|   const dispatch = createEventDispatcher<SettingsEventType>(); | ||||
| 
 | ||||
|   let isConfirmOpen = false; | ||||
|   let handleConfirm: (value: boolean) => void; | ||||
| 
 | ||||
|   const openConfirmModal = () => { | ||||
|     return new Promise((resolve) => { | ||||
|       handleConfirm = (value: boolean) => { | ||||
|         isConfirmOpen = false; | ||||
|         resolve(value); | ||||
|       }; | ||||
|       isConfirmOpen = true; | ||||
|     }); | ||||
|   }; | ||||
| 
 | ||||
|   async function handleSave() { | ||||
|     if (!savedConfig.oauth.enabled && savedConfig.passwordLogin.enabled && !config.passwordLogin.enabled) { | ||||
|       const confirmed = await openConfirmModal(); | ||||
|       if (!confirmed) { | ||||
|         return; | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     dispatch('save', { passwordLogin: config.passwordLogin }); | ||||
|   } | ||||
| </script> | ||||
| 
 | ||||
| {#if isConfirmOpen} | ||||
|   <ConfirmDisableLogin onCancel={() => handleConfirm(false)} onConfirm={() => handleConfirm(true)} /> | ||||
| {/if} | ||||
| 
 | ||||
| <div> | ||||
|   <div in:fade={{ duration: 500 }}> | ||||
|     <form autocomplete="off" on:submit|preventDefault> | ||||
|       <div class="ml-4 mt-4 flex flex-col"> | ||||
|         <SettingSwitch | ||||
|           id="enable-password-login" | ||||
|           title="ENABLED" | ||||
|           {disabled} | ||||
|           subtitle="Login with email and password" | ||||
|           bind:checked={config.passwordLogin.enabled} | ||||
|         /> | ||||
| 
 | ||||
|         <SettingButtonsRow | ||||
|           on:reset={({ detail }) => dispatch('reset', { ...detail, configKeys: ['passwordLogin'] })} | ||||
|           on:save={() => handleSave()} | ||||
|           showResetToDefault={!isEqual(savedConfig.passwordLogin, defaultConfig.passwordLogin)} | ||||
|           {disabled} | ||||
|         /> | ||||
|       </div> | ||||
|     </form> | ||||
|   </div> | ||||
| </div> | ||||
| @ -1,34 +1,33 @@ | ||||
| <script lang="ts"> | ||||
|   import AdminSettings from '$lib/components/admin-page/settings/admin-settings.svelte'; | ||||
|   import AuthSettings from '$lib/components/admin-page/settings/auth/auth-settings.svelte'; | ||||
|   import FFmpegSettings from '$lib/components/admin-page/settings/ffmpeg/ffmpeg-settings.svelte'; | ||||
|   import ImageSettings from '$lib/components/admin-page/settings/image/image-settings.svelte'; | ||||
|   import JobSettings from '$lib/components/admin-page/settings/job-settings/job-settings.svelte'; | ||||
|   import LibrarySettings from '$lib/components/admin-page/settings/library-settings/library-settings.svelte'; | ||||
|   import LoggingSettings from '$lib/components/admin-page/settings/logging-settings/logging-settings.svelte'; | ||||
|   import MachineLearningSettings from '$lib/components/admin-page/settings/machine-learning-settings/machine-learning-settings.svelte'; | ||||
|   import MapSettings from '$lib/components/admin-page/settings/map-settings/map-settings.svelte'; | ||||
|   import NewVersionCheckSettings from '$lib/components/admin-page/settings/new-version-check-settings/new-version-check-settings.svelte'; | ||||
|   import OAuthSettings from '$lib/components/admin-page/settings/oauth/oauth-settings.svelte'; | ||||
|   import PasswordLoginSettings from '$lib/components/admin-page/settings/password-login/password-login-settings.svelte'; | ||||
|   import ServerSettings from '$lib/components/admin-page/settings/server/server-settings.svelte'; | ||||
|   import NotificationSettings from '$lib/components/admin-page/settings/notification-settings/notification-settings.svelte'; | ||||
|   import SettingAccordion from '$lib/components/shared-components/settings/setting-accordion.svelte'; | ||||
|   import ServerSettings from '$lib/components/admin-page/settings/server/server-settings.svelte'; | ||||
|   import StorageTemplateSettings from '$lib/components/admin-page/settings/storage-template/storage-template-settings.svelte'; | ||||
|   import ThemeSettings from '$lib/components/admin-page/settings/theme/theme-settings.svelte'; | ||||
|   import ImageSettings from '$lib/components/admin-page/settings/image/image-settings.svelte'; | ||||
|   import TrashSettings from '$lib/components/admin-page/settings/trash-settings/trash-settings.svelte'; | ||||
|   import UserSettings from '$lib/components/admin-page/settings/user-settings/user-settings.svelte'; | ||||
|   import LinkButton from '$lib/components/elements/buttons/link-button.svelte'; | ||||
|   import Icon from '$lib/components/elements/icon.svelte'; | ||||
|   import UserPageLayout from '$lib/components/layouts/user-page-layout.svelte'; | ||||
|   import SettingAccordionState from '$lib/components/shared-components/settings/setting-accordion-state.svelte'; | ||||
|   import SettingAccordion from '$lib/components/shared-components/settings/setting-accordion.svelte'; | ||||
|   import { QueryParameter } from '$lib/constants'; | ||||
|   import { downloadManager } from '$lib/stores/download'; | ||||
|   import { featureFlags } from '$lib/stores/server-config.store'; | ||||
|   import { copyToClipboard } from '$lib/utils'; | ||||
|   import { downloadBlob } from '$lib/utils/asset-utils'; | ||||
|   import type { SystemConfigDto } from '@immich/sdk'; | ||||
|   import { mdiAlert, mdiContentCopy, mdiDownload, mdiUpload } from '@mdi/js'; | ||||
|   import type { PageData } from './$types'; | ||||
|   import SettingAccordionState from '$lib/components/shared-components/settings/setting-accordion-state.svelte'; | ||||
|   import { QueryParameter } from '$lib/constants'; | ||||
|   import type { SystemConfigDto } from '@immich/sdk'; | ||||
| 
 | ||||
|   export let data: PageData; | ||||
| 
 | ||||
| @ -36,13 +35,12 @@ | ||||
|   let handleSave: (update: Partial<SystemConfigDto>) => Promise<void>; | ||||
| 
 | ||||
|   type Settings = | ||||
|     | typeof AuthSettings | ||||
|     | typeof JobSettings | ||||
|     | typeof LibrarySettings | ||||
|     | typeof LoggingSettings | ||||
|     | typeof MachineLearningSettings | ||||
|     | typeof MapSettings | ||||
|     | typeof OAuthSettings | ||||
|     | typeof PasswordLoginSettings | ||||
|     | typeof ServerSettings | ||||
|     | typeof StorageTemplateSettings | ||||
|     | typeof ThemeSettings | ||||
| @ -82,6 +80,12 @@ | ||||
|     subtitle: string; | ||||
|     key: string; | ||||
|   }> = [ | ||||
|     { | ||||
|       item: AuthSettings, | ||||
|       title: 'Authentication Settings', | ||||
|       subtitle: 'Manage password, OAuth, and other authentication settings', | ||||
|       key: 'image', | ||||
|     }, | ||||
|     { | ||||
|       item: ImageSettings, | ||||
|       title: 'Image Settings', | ||||
| @ -124,18 +128,6 @@ | ||||
|       subtitle: 'Manage notification settings, including email', | ||||
|       key: 'notifications', | ||||
|     }, | ||||
|     { | ||||
|       item: OAuthSettings, | ||||
|       title: 'OAuth Authentication', | ||||
|       subtitle: 'Manage the login with OAuth settings', | ||||
|       key: 'oauth', | ||||
|     }, | ||||
|     { | ||||
|       item: PasswordLoginSettings, | ||||
|       title: 'Password Authentication', | ||||
|       subtitle: 'Manage the login with password settings', | ||||
|       key: 'password', | ||||
|     }, | ||||
|     { | ||||
|       item: ServerSettings, | ||||
|       title: 'Server Settings', | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user