mirror of
https://github.com/zammad/zammad
synced 2026-05-24 09:48:36 +00:00
149 lines
4.7 KiB
TypeScript
149 lines
4.7 KiB
TypeScript
// Copyright (C) 2012-2026 Zammad Foundation, https://zammad-foundation.org/
|
|
|
|
import { computed, type Ref } from 'vue'
|
|
|
|
import {
|
|
NotificationTypes,
|
|
useNotifications,
|
|
} from '#shared/components/CommonNotifications/index.ts'
|
|
import type { TicketArticle } from '#shared/entities/ticket/types.ts'
|
|
import { translateArticleSecurity } from '#shared/entities/ticket-article/composables/translateArticleSecurity.ts'
|
|
import { useTicketArticleRetrySecurityProcessMutation } from '#shared/entities/ticket-article/graphql/mutations/ticketArticleRetrySecurityProcess.api.ts'
|
|
import { i18n } from '#shared/i18n/index.ts'
|
|
import { MutationHandler } from '#shared/server/apollo/handler/index.ts'
|
|
|
|
export const useArticleSecurity = (article: Ref<TicketArticle>) => {
|
|
const { notify } = useNotifications()
|
|
|
|
const signingSuccess = computed(() => article.value?.securityState?.signingSuccess)
|
|
|
|
const signingMessage = computed(() => article.value?.securityState?.signingMessage)
|
|
|
|
const encryptionSuccess = computed(() => article.value?.securityState?.encryptionSuccess)
|
|
|
|
const encryptionMessage = computed(() => article.value?.securityState?.encryptionMessage)
|
|
|
|
const isEncrypted = computed(
|
|
() =>
|
|
article.value.securityState?.encryptionSuccess ||
|
|
(article.value.securityState?.encryptionSuccess === false &&
|
|
article.value.securityState?.encryptionMessage),
|
|
)
|
|
|
|
const isSigned = computed(
|
|
() =>
|
|
article.value.securityState?.signingSuccess ||
|
|
(article.value.securityState?.signingSuccess === false &&
|
|
article.value.securityState?.signingMessage),
|
|
)
|
|
|
|
const hasSecurityAttribute = computed(
|
|
() => article.value.securityState && (isEncrypted.value || isSigned.value),
|
|
)
|
|
|
|
const hasError = computed(() => {
|
|
if (!article.value.securityState) return false
|
|
|
|
if (
|
|
article?.value.securityState?.signingSuccess === false &&
|
|
article?.value.securityState?.signingMessage
|
|
)
|
|
return true
|
|
|
|
return !!(
|
|
article?.value.securityState?.encryptionSuccess === false &&
|
|
article?.value.securityState?.encryptionMessage
|
|
)
|
|
})
|
|
|
|
const retrySecurityProcess = async () => {
|
|
const retryMutation = new MutationHandler(
|
|
useTicketArticleRetrySecurityProcessMutation(() => ({
|
|
variables: {
|
|
articleId: article.value.id,
|
|
},
|
|
})),
|
|
)
|
|
|
|
const result = await retryMutation.send()
|
|
const security = result?.ticketArticleRetrySecurityProcess?.retryResult
|
|
|
|
if (!security) {
|
|
return notify({
|
|
id: 'retry-security-error',
|
|
type: NotificationTypes.Error,
|
|
message: __('The retried security process failed!'),
|
|
timeout: 2000,
|
|
})
|
|
}
|
|
|
|
if (security.type !== article.value?.securityState?.type) {
|
|
// shouldn't be possible, we only support S/MIME
|
|
return notify({
|
|
id: 'security-mechanism-error',
|
|
type: NotificationTypes.Error,
|
|
message: __('Article uses different security mechanism.'),
|
|
timeout: 2000,
|
|
})
|
|
}
|
|
|
|
if (security.signingSuccess) {
|
|
notify({
|
|
id: 'signature-verified',
|
|
type: NotificationTypes.Success,
|
|
message: __('The signature was successfully verified.'),
|
|
})
|
|
} else if (security.signingMessage) {
|
|
notify({
|
|
id: 'signature-verification-failed',
|
|
type: NotificationTypes.Error,
|
|
message: __('Signature verification failed! %s'),
|
|
messagePlaceholder: [i18n.t(security.signingMessage)],
|
|
timeout: 2000,
|
|
})
|
|
}
|
|
|
|
if (security.encryptionSuccess) {
|
|
notify({
|
|
id: 'decryption-success',
|
|
type: NotificationTypes.Success,
|
|
message: __('Decryption was successful.'),
|
|
})
|
|
} else if (security.encryptionMessage) {
|
|
notify({
|
|
id: 'decryption-failed',
|
|
type: NotificationTypes.Error,
|
|
message: __('Decryption failed! %s'),
|
|
messagePlaceholder: [i18n.t(security.encryptionMessage)],
|
|
timeout: 2000,
|
|
})
|
|
}
|
|
}
|
|
|
|
const typeLabel = computed(() => {
|
|
if (!article.value?.securityState?.type) return
|
|
|
|
return translateArticleSecurity(article.value?.securityState?.type)
|
|
})
|
|
|
|
return {
|
|
hasError,
|
|
signingSuccess,
|
|
signingMessage,
|
|
encryptionSuccess,
|
|
encryptionMessage,
|
|
isEncrypted,
|
|
isSigned,
|
|
hasSecurityAttribute,
|
|
typeLabel,
|
|
signingIcon: computed(() => (signingSuccess.value ? 'signing-success' : 'signing-fail')),
|
|
encryptionIcon: computed(() =>
|
|
encryptionSuccess.value ? 'encryption-success' : 'encryption-fail',
|
|
),
|
|
signedStatusMessage: computed(() => (signingSuccess.value ? __('Signed') : __('Sign error'))),
|
|
encryptedStatusMessage: computed(() =>
|
|
encryptionSuccess.value ? __('Encrypted') : __('Encryption error'),
|
|
),
|
|
retrySecurityProcess,
|
|
}
|
|
}
|