generated from Nodarx/template
refactor: bunch of improvements
Signed-off-by: Sebastian Krupinski <krupinski01@gmail.com>
This commit is contained in:
@@ -1,22 +1,22 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, ref, watch } from 'vue'
|
||||
import { IdentityBasic } from '@KTXM/MailManager/models/identity'
|
||||
import { ServiceObject } from '@KTXM/MailManager/models/service'
|
||||
import type { ServiceIdentity } from '@KTXM/MailManager/types/service'
|
||||
import type { ProviderAuthPanelProps, ProviderAuthPanelEmits } from '@KTXM/MailManager/types/integration'
|
||||
|
||||
const props = defineProps<ProviderAuthPanelProps>()
|
||||
const emit = defineEmits<ProviderAuthPanelEmits>()
|
||||
|
||||
const identity = ref(props.prefilledIdentity || props.emailAddress || '')
|
||||
const secret = ref(props.prefilledSecret || '')
|
||||
const identity = ref('')
|
||||
const secret = ref('')
|
||||
|
||||
const rules = {
|
||||
required: (value: unknown) => !!value || 'This field is required'
|
||||
}
|
||||
|
||||
const isValid = computed(() => !!identity.value && !!secret.value)
|
||||
|
||||
const currentIdentity = computed((): ServiceIdentity | null => {
|
||||
if (!isValid.value) {
|
||||
if (!identity.value || !secret.value) {
|
||||
return null
|
||||
}
|
||||
|
||||
@@ -28,33 +28,13 @@ const currentIdentity = computed((): ServiceIdentity | null => {
|
||||
})
|
||||
|
||||
watch(
|
||||
currentIdentity,
|
||||
value => {
|
||||
if (value) {
|
||||
emit('update:modelValue', value)
|
||||
}
|
||||
},
|
||||
{ immediate: true, deep: true }
|
||||
)
|
||||
|
||||
watch(
|
||||
isValid,
|
||||
value => {
|
||||
emit('valid', value)
|
||||
() => props.service,
|
||||
service => {
|
||||
syncFromService(service)
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
value => {
|
||||
if (value?.type === 'BA') {
|
||||
identity.value = value.identity || ''
|
||||
secret.value = value.secret || ''
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
watch(
|
||||
() => props.emailAddress,
|
||||
value => {
|
||||
@@ -64,6 +44,55 @@ watch(
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
|
||||
watch(
|
||||
currentIdentity,
|
||||
value => {
|
||||
const existingIdentity = props.service?.identity?.toJson() ?? null
|
||||
if (sameIdentity(existingIdentity, value)) {
|
||||
return
|
||||
}
|
||||
|
||||
const nextService = createServiceObject(props.service)
|
||||
nextService.identity = value ? new IdentityBasic(value.identity, value.secret) : null
|
||||
emit('update:service', nextService)
|
||||
},
|
||||
{ immediate: true, deep: true }
|
||||
)
|
||||
|
||||
function syncFromService(service?: ServiceObject) {
|
||||
const serviceIdentity = service?.identity?.toJson() ?? null
|
||||
|
||||
if (serviceIdentity?.type === 'BA') {
|
||||
identity.value = serviceIdentity.identity || props.prefilledIdentity || props.emailAddress || ''
|
||||
secret.value = serviceIdentity.secret || props.prefilledSecret || ''
|
||||
return
|
||||
}
|
||||
|
||||
identity.value = props.prefilledIdentity || props.emailAddress || ''
|
||||
secret.value = props.prefilledSecret || ''
|
||||
}
|
||||
|
||||
function createServiceObject(service?: ServiceObject): ServiceObject {
|
||||
const nextService = new ServiceObject()
|
||||
|
||||
if (service) {
|
||||
nextService.fromJson(service.toJson())
|
||||
}
|
||||
|
||||
return nextService
|
||||
}
|
||||
|
||||
function sameIdentity(a: ServiceIdentity | null, b: ServiceIdentity | null): boolean {
|
||||
if (a === null || b === null) {
|
||||
return a === b
|
||||
}
|
||||
|
||||
return a.type === 'BA'
|
||||
&& b.type === 'BA'
|
||||
&& a.identity === b.identity
|
||||
&& a.secret === b.secret
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
@@ -1,66 +1,26 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, ref, watch } from 'vue'
|
||||
import { LocationSocketSole } from '@KTXM/MailManager/models/location'
|
||||
import { ServiceObject } from '@KTXM/MailManager/models/service'
|
||||
import type {
|
||||
ServiceLocation,
|
||||
ServiceLocationSocketSole,
|
||||
ServiceLocationUri,
|
||||
} from '@KTXM/MailManager/types/service'
|
||||
import type { ProviderConfigPanelProps, ProviderConfigPanelEmits } from '@KTXM/MailManager/types/integration'
|
||||
import type {
|
||||
ProviderProtocolPanelProps,
|
||||
ProviderProtocolPanelEmits,
|
||||
} from '@KTXM/MailManager/types/integration'
|
||||
|
||||
type ImapEncryption = 'none' | 'ssl' | 'tls' | 'starttls'
|
||||
|
||||
type ImapLocation = ServiceLocationSocketSole & {
|
||||
type: 'SOCKET_SOLE' | 'URI'
|
||||
verifyPeerName?: boolean
|
||||
allowSelfSigned?: boolean
|
||||
}
|
||||
const props = defineProps<ProviderProtocolPanelProps>()
|
||||
const emit = defineEmits<ProviderProtocolPanelEmits>()
|
||||
|
||||
const props = defineProps<ProviderConfigPanelProps>()
|
||||
const emit = defineEmits<ProviderConfigPanelEmits>()
|
||||
|
||||
function asImapLocation(location?: ServiceLocation): ImapLocation | null {
|
||||
if (!location) {
|
||||
return null
|
||||
}
|
||||
|
||||
if (location.type === 'SOCKET_SOLE') {
|
||||
return location as ImapLocation
|
||||
}
|
||||
|
||||
if (location.type === 'URI') {
|
||||
const uriLocation = location as ServiceLocationUri & {
|
||||
encryption?: ImapEncryption
|
||||
verifyPeerName?: boolean
|
||||
allowSelfSigned?: boolean
|
||||
}
|
||||
|
||||
return {
|
||||
type: 'URI',
|
||||
host: uriLocation.host || '',
|
||||
port: uriLocation.port || 993,
|
||||
encryption: uriLocation.encryption || 'ssl',
|
||||
verifyPeer: uriLocation.verifyPeer ?? true,
|
||||
verifyHost: uriLocation.verifyPeerName ?? uriLocation.verifyHost ?? true,
|
||||
verifyPeerName: uriLocation.verifyPeerName ?? uriLocation.verifyHost ?? true,
|
||||
allowSelfSigned: uriLocation.allowSelfSigned ?? false,
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
function defaultPortFor(encryption: ImapEncryption): number {
|
||||
return encryption === 'ssl' || encryption === 'tls' ? 993 : 143
|
||||
}
|
||||
|
||||
const sourceLocation = computed(() => asImapLocation(props.modelValue || props.discoveredLocation))
|
||||
|
||||
const host = ref(sourceLocation.value?.host || '')
|
||||
const encryption = ref<ImapEncryption>(sourceLocation.value?.encryption || 'ssl')
|
||||
const port = ref(String(sourceLocation.value?.port || defaultPortFor(encryption.value)))
|
||||
const verifyPeer = ref(sourceLocation.value?.verifyPeer ?? true)
|
||||
const verifyHost = ref(sourceLocation.value?.verifyPeerName ?? sourceLocation.value?.verifyHost ?? true)
|
||||
const allowSelfSigned = ref(sourceLocation.value?.allowSelfSigned ?? false)
|
||||
const host = ref('')
|
||||
const encryption = ref<ImapEncryption>('ssl')
|
||||
const port = ref('993')
|
||||
const verifyPeer = ref(true)
|
||||
const verifyHost = ref(true)
|
||||
|
||||
const encryptionOptions = [
|
||||
{ title: 'Implicit TLS (SSL)', value: 'ssl' },
|
||||
@@ -81,93 +41,98 @@ const rules = {
|
||||
|
||||
const isValid = computed(() => !!host.value && rules.port(port.value) === true)
|
||||
|
||||
const currentLocation = computed((): ServiceLocation | null => {
|
||||
const currentLocation = computed((): ServiceLocationSocketSole | null => {
|
||||
if (!isValid.value) {
|
||||
return null
|
||||
}
|
||||
|
||||
const numericPort = Number(port.value)
|
||||
const location: ImapLocation = {
|
||||
return {
|
||||
type: 'SOCKET_SOLE',
|
||||
host: host.value,
|
||||
port: numericPort,
|
||||
port: Number(port.value),
|
||||
encryption: encryption.value,
|
||||
verifyPeer: verifyPeer.value,
|
||||
verifyHost: verifyHost.value,
|
||||
verifyPeerName: verifyHost.value,
|
||||
allowSelfSigned: allowSelfSigned.value,
|
||||
}
|
||||
|
||||
return location as ServiceLocation
|
||||
})
|
||||
|
||||
watch(
|
||||
() => [props.service, props.discoveredLocation] as const,
|
||||
([service, discoveredLocation]) => {
|
||||
syncFromLocation(service?.location?.toJson() ?? discoveredLocation ?? null)
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
|
||||
watch(
|
||||
currentLocation,
|
||||
value => {
|
||||
if (value) {
|
||||
emit('update:modelValue', value)
|
||||
location => {
|
||||
const existingLocation = props.service?.location?.toJson() ?? null
|
||||
if (sameLocation(existingLocation, location)) {
|
||||
return
|
||||
}
|
||||
|
||||
const nextService = createServiceObject(props.service)
|
||||
nextService.location = location ? LocationSocketSole.fromJson(location) : null
|
||||
emit('update:service', nextService)
|
||||
},
|
||||
{ immediate: true, deep: true }
|
||||
)
|
||||
|
||||
watch(
|
||||
isValid,
|
||||
value => {
|
||||
emit('valid', value)
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
value => {
|
||||
const next = asImapLocation(value)
|
||||
if (!next) {
|
||||
return
|
||||
}
|
||||
|
||||
host.value = next.host || ''
|
||||
encryption.value = next.encryption || 'ssl'
|
||||
port.value = String(next.port || defaultPortFor(encryption.value))
|
||||
verifyPeer.value = next.verifyPeer ?? true
|
||||
verifyHost.value = next.verifyPeerName ?? next.verifyHost ?? true
|
||||
allowSelfSigned.value = next.allowSelfSigned ?? false
|
||||
}
|
||||
)
|
||||
|
||||
watch(
|
||||
() => props.discoveredLocation,
|
||||
value => {
|
||||
if (props.modelValue) {
|
||||
return
|
||||
}
|
||||
|
||||
const next = asImapLocation(value)
|
||||
if (!next) {
|
||||
return
|
||||
}
|
||||
|
||||
host.value = next.host || ''
|
||||
encryption.value = next.encryption || 'ssl'
|
||||
port.value = String(next.port || defaultPortFor(encryption.value))
|
||||
verifyPeer.value = next.verifyPeer ?? true
|
||||
verifyHost.value = next.verifyPeerName ?? next.verifyHost ?? true
|
||||
allowSelfSigned.value = next.allowSelfSigned ?? false
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
|
||||
watch(encryption, (next, previous) => {
|
||||
const previousDefault = defaultPortFor(previous)
|
||||
if (!port.value || Number(port.value) === previousDefault) {
|
||||
port.value = String(defaultPortFor(next))
|
||||
}
|
||||
})
|
||||
|
||||
function syncFromLocation(location: ServiceLocation | null) {
|
||||
const socketLocation = getSocketLocation(location)
|
||||
|
||||
host.value = socketLocation?.host ?? ''
|
||||
encryption.value = socketLocation?.encryption ?? 'ssl'
|
||||
port.value = String(socketLocation?.port ?? defaultPortFor(encryption.value))
|
||||
verifyPeer.value = socketLocation?.verifyPeer ?? true
|
||||
verifyHost.value = socketLocation?.verifyHost ?? true
|
||||
}
|
||||
|
||||
function createServiceObject(service?: ServiceObject): ServiceObject {
|
||||
const nextService = new ServiceObject()
|
||||
|
||||
if (service) {
|
||||
nextService.fromJson(service.toJson())
|
||||
}
|
||||
|
||||
return nextService
|
||||
}
|
||||
|
||||
function getSocketLocation(location?: ServiceLocation | null): ServiceLocationSocketSole | null {
|
||||
return location?.type === 'SOCKET_SOLE' ? location : null
|
||||
}
|
||||
|
||||
function sameLocation(a: ServiceLocation | null, b: ServiceLocation | null): boolean {
|
||||
if (a === null || b === null) {
|
||||
return a === b
|
||||
}
|
||||
|
||||
if (a.type !== 'SOCKET_SOLE' || b.type !== 'SOCKET_SOLE') {
|
||||
return false
|
||||
}
|
||||
|
||||
return a.host === b.host
|
||||
&& a.port === b.port
|
||||
&& a.encryption === b.encryption
|
||||
&& (a.verifyPeer ?? true) === (b.verifyPeer ?? true)
|
||||
&& (a.verifyHost ?? true) === (b.verifyHost ?? true)
|
||||
}
|
||||
|
||||
function defaultPortFor(nextEncryption: ImapEncryption): number {
|
||||
return nextEncryption === 'ssl' || nextEncryption === 'tls' ? 993 : 143
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="imap-config-panel">
|
||||
<div class="imap-protocol-panel">
|
||||
<h3 class="text-h6 mb-4">IMAP Connection Settings</h3>
|
||||
<p class="text-body-2 mb-6">Configure the server address, transport security, and certificate verification for your IMAP mailbox.</p>
|
||||
|
||||
@@ -232,14 +197,6 @@ watch(encryption, (next, previous) => {
|
||||
persistent-hint
|
||||
class="mb-4"
|
||||
/>
|
||||
|
||||
<v-switch
|
||||
v-model="allowSelfSigned"
|
||||
label="Allow self-signed certificates"
|
||||
color="primary"
|
||||
hint="Use only when your server is intentionally deployed with a self-signed certificate"
|
||||
persistent-hint
|
||||
/>
|
||||
</v-expansion-panel-text>
|
||||
</v-expansion-panel>
|
||||
</v-expansion-panels>
|
||||
@@ -256,7 +213,7 @@ watch(encryption, (next, previous) => {
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.imap-config-panel {
|
||||
.imap-protocol-panel {
|
||||
max-width: 800px;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user