Просмотр исходного кода

Fixes: PGP - Security type switch in mobile view does not respect configured default behavior.

Dusan Vuckovic 1 год назад
Родитель
Сommit
e47eea8c07

+ 9 - 4
app/frontend/shared/components/Form/fields/FieldSecurity/FieldSecurity.vue

@@ -9,10 +9,11 @@ import { i18n } from '#shared/i18n.ts'
 import { translateArticleSecurity } from '#shared/entities/ticket-article/composables/translateArticleSecurity.ts'
 import { translateArticleSecurity } from '#shared/entities/ticket-article/composables/translateArticleSecurity.ts'
 import useValue from '../../composables/useValue.ts'
 import useValue from '../../composables/useValue.ts'
 import type {
 import type {
+  SecurityAllowed,
+  SecurityDefaultOptions,
+  SecurityMessages,
   SecurityOption,
   SecurityOption,
   SecurityValue,
   SecurityValue,
-  SecurityMessages,
-  SecurityAllowed,
 } from './types.ts'
 } from './types.ts'
 import { EnumSecurityStateType } from './types.ts'
 import { EnumSecurityStateType } from './types.ts'
 import type { FormFieldContext } from '../../types/field.ts'
 import type { FormFieldContext } from '../../types/field.ts'
@@ -21,6 +22,7 @@ interface FieldSecurityProps {
   context: FormFieldContext<{
   context: FormFieldContext<{
     disabled?: boolean
     disabled?: boolean
     securityAllowed?: SecurityAllowed
     securityAllowed?: SecurityAllowed
+    securityDefaultOptions?: SecurityDefaultOptions
     securityMessages?: SecurityMessages
     securityMessages?: SecurityMessages
   }>
   }>
 }
 }
@@ -125,9 +127,12 @@ const tooltipMessages = computed(() => {
   return messages
   return messages
 })
 })
 
 
+const defaultOptions = (method: EnumSecurityStateType) =>
+  props.context.securityDefaultOptions?.[method] || []
+
 const changeSecurityState = (method: EnumSecurityStateType) => {
 const changeSecurityState = (method: EnumSecurityStateType) => {
-  // remove unsupported options
-  const newOptions = filterOptions(method, localValue.value?.options || [])
+  // Reset the default behavior of the chosen method and remove unsupported options.
+  const newOptions = filterOptions(method, defaultOptions(method))
   localValue.value = {
   localValue.value = {
     method,
     method,
     options: newOptions,
     options: newOptions,

+ 9 - 1
app/frontend/shared/components/Form/fields/FieldSecurity/__tests__/FieldSecurity.spec.ts

@@ -27,6 +27,10 @@ describe('FieldSecurity', () => {
         [EnumSecurityStateType.Pgp]: ['encryption', 'sign'],
         [EnumSecurityStateType.Pgp]: ['encryption', 'sign'],
         [EnumSecurityStateType.Smime]: ['encryption', 'sign'],
         [EnumSecurityStateType.Smime]: ['encryption', 'sign'],
       },
       },
+      securityDefaultOptions: {
+        [EnumSecurityStateType.Pgp]: ['encryption', 'sign'],
+        [EnumSecurityStateType.Smime]: ['encryption', 'sign'],
+      },
     })
     })
 
 
     const node = getNode('security')!
     const node = getNode('security')!
@@ -64,7 +68,7 @@ describe('FieldSecurity', () => {
 
 
     expect(node.context?._value).toEqual({
     expect(node.context?._value).toEqual({
       method: EnumSecurityStateType.Pgp,
       method: EnumSecurityStateType.Pgp,
-      options: ['encryption'],
+      options: ['encryption', 'sign'],
     })
     })
   })
   })
 
 
@@ -116,6 +120,10 @@ describe('FieldSecurity', () => {
         [EnumSecurityStateType.Smime]: ['encryption', 'sign'],
         [EnumSecurityStateType.Smime]: ['encryption', 'sign'],
         [EnumSecurityStateType.Pgp]: ['sign'],
         [EnumSecurityStateType.Pgp]: ['sign'],
       },
       },
+      securityDefaultOptions: {
+        [EnumSecurityStateType.Smime]: ['sign'],
+        [EnumSecurityStateType.Pgp]: ['sign'],
+      },
     })
     })
 
 
     const node = getNode('security')!
     const node = getNode('security')!

+ 1 - 0
app/frontend/shared/components/Form/fields/FieldSecurity/index.ts

@@ -5,6 +5,7 @@ import FieldSecurity from './FieldSecurity.vue'
 
 
 const fieldDefinition = createInput(FieldSecurity, [
 const fieldDefinition = createInput(FieldSecurity, [
   'securityAllowed',
   'securityAllowed',
+  'securityDefaultOptions',
   'securityMessages',
   'securityMessages',
 ])
 ])
 
 

+ 1 - 0
app/frontend/shared/components/Form/fields/FieldSecurity/types.ts

@@ -6,6 +6,7 @@ export { EnumSecurityStateType } from '#shared/graphql/types.ts'
 
 
 export type SecurityOption = 'encryption' | 'sign'
 export type SecurityOption = 'encryption' | 'sign'
 export type SecurityAllowed = Record<EnumSecurityStateType, SecurityOption[]>
 export type SecurityAllowed = Record<EnumSecurityStateType, SecurityOption[]>
+export type SecurityDefaultOptions = SecurityAllowed
 export type SecurityValue =
 export type SecurityValue =
   | { method: EnumSecurityStateType; options: SecurityOption[] }
   | { method: EnumSecurityStateType; options: SecurityOption[] }
   | null
   | null

+ 10 - 5
app/models/form_updater/concerns/has_security_options.rb

@@ -28,14 +28,19 @@ module FormUpdater::Concerns::HasSecurityOptions
 
 
   def map_result(target, type, result_method, mapped_type)
   def map_result(target, type, result_method, mapped_type)
     push_to_sub_array(target, [:securityAllowed, type], mapped_type, result_method.possible?)
     push_to_sub_array(target, [:securityAllowed, type], mapped_type, result_method.possible?)
-    target[:value] ||= {}
-    if !target[:value]['method'] || target[:value]['method'] == type
-      target[:value]['method'] ||= type
-      push_to_sub_array(target, [:value, 'options'], mapped_type, result_method.active_by_default?)
-    end
+    push_to_sub_array(target, [:securityDefaultOptions, type], mapped_type, result_method.active_by_default?)
+    initialize_value(target, type, result_method, mapped_type)
     set_sub_hash(target, [:securityMessages, type, mapped_type], map_message(result_method), result_method.message.present?)
     set_sub_hash(target, [:securityMessages, type, mapped_type], map_message(result_method), result_method.message.present?)
   end
   end
 
 
+  def initialize_value(target, type, result_method, mapped_type)
+    target[:value] ||= {}
+    return if target[:value]['method'] && target[:value]['method'] != type
+
+    target[:value]['method'] ||= type
+    push_to_sub_array(target, [:value, 'options'], mapped_type, result_method.active_by_default?)
+  end
+
   def map_message(result_method)
   def map_message(result_method)
     { message: result_method.message, messagePlaceholder: result_method.message_placeholders }
     { message: result_method.message, messagePlaceholder: result_method.message_placeholders }
   end
   end

+ 94 - 24
spec/models/form_updater/concerns/has_security_options_examples.rb

@@ -39,7 +39,11 @@ RSpec.shared_examples 'HasSecurityOptions' do |type:|
       end
       end
     end
     end
 
 
-    it_behaves_like 'resolving security field', expected_result: { securityAllowed: { 'SMIME'=>[] }, value: { 'method' => 'SMIME', 'options' => [] } }
+    it_behaves_like 'resolving security field', expected_result: {
+      securityAllowed:        { 'SMIME' => [] },
+      securityDefaultOptions: { 'SMIME' => [] },
+      value:                  { 'method' => 'SMIME', 'options' => [] },
+    }
 
 
     context 'when PGP is activated as well' do
     context 'when PGP is activated as well' do
       before do
       before do
@@ -52,7 +56,12 @@ RSpec.shared_examples 'HasSecurityOptions' do |type:|
           'SMIME' => { 'encryption' => { message: 'There was no recipient found.', messagePlaceholder: [] }, 'sign' => { message: 'There was no certificate found.', messagePlaceholder: [] } }
           'SMIME' => { 'encryption' => { message: 'There was no recipient found.', messagePlaceholder: [] }, 'sign' => { message: 'There was no certificate found.', messagePlaceholder: [] } }
         }
         }
 
 
-      it_behaves_like 'resolving security field', expected_result: { securityAllowed: { 'SMIME' => [], 'PGP' => [] }, value: { 'method' => 'SMIME', 'options' => [] }, securityMessages: security_messages }
+      it_behaves_like 'resolving security field', expected_result: {
+        securityAllowed:        { 'SMIME' => [], 'PGP' => [] },
+        securityDefaultOptions: { 'SMIME' => [], 'PGP' => [] },
+        value:                  { 'method' => 'SMIME', 'options' => [] },
+        securityMessages:       security_messages,
+      }
     end
     end
 
 
     context 'when secure mailing is not configured' do
     context 'when secure mailing is not configured' do
@@ -114,9 +123,10 @@ RSpec.shared_examples 'HasSecurityOptions' do |type:|
       end
       end
 
 
       it_behaves_like 'resolving security field', expected_result: {
       it_behaves_like 'resolving security field', expected_result: {
-        securityAllowed:  { 'SMIME'=>[] },
-        value:            { 'method' => 'SMIME', 'options' => [] },
-        securityMessages: { 'SMIME'=>{ 'encryption' => { message: "Can't find S/MIME encryption certificates for: smime2@example.com", messagePlaceholder: [] }, 'sign' => { message: 'There was no certificate found.', messagePlaceholder: [] } } }
+        securityAllowed:        { 'SMIME' => [] },
+        securityDefaultOptions: { 'SMIME' => [] },
+        value:                  { 'method' => 'SMIME', 'options' => [] },
+        securityMessages:       { 'SMIME'=>{ 'encryption' => { message: "Can't find S/MIME encryption certificates for: smime2@example.com", messagePlaceholder: [] }, 'sign' => { message: 'There was no certificate found.', messagePlaceholder: [] } } }
       }
       }
 
 
       context 'with recipient certificate present' do
       context 'with recipient certificate present' do
@@ -125,9 +135,10 @@ RSpec.shared_examples 'HasSecurityOptions' do |type:|
         end
         end
 
 
         it_behaves_like 'resolving security field', expected_result: {
         it_behaves_like 'resolving security field', expected_result: {
-          securityAllowed:  { 'SMIME'=>['encryption'] },
-          value:            { 'method' => 'SMIME', 'options' => ['encryption'] },
-          securityMessages: { 'SMIME'=>{ 'encryption' => { message: 'The certificates for %s were found.', messagePlaceholder: ['smime2@example.com'] }, 'sign' => { message: 'There was no certificate found.', messagePlaceholder: [] } } }
+          securityAllowed:        { 'SMIME' => ['encryption'] },
+          securityDefaultOptions: { 'SMIME' => ['encryption'] },
+          value:                  { 'method' => 'SMIME', 'options' => ['encryption'] },
+          securityMessages:       { 'SMIME' => { 'encryption' => { message: 'The certificates for %s were found.', messagePlaceholder: ['smime2@example.com'] }, 'sign' => { message: 'There was no certificate found.', messagePlaceholder: [] } } }
         }
         }
       end
       end
     end
     end
@@ -145,20 +156,32 @@ RSpec.shared_examples 'HasSecurityOptions' do |type:|
         end
         end
       end
       end
 
 
-      it_behaves_like 'resolving security field', expected_result: { securityAllowed: { 'SMIME'=>[] }, value: { 'method' => 'SMIME', 'options' => [] } }
+      it_behaves_like 'resolving security field', expected_result: {
+        securityAllowed:        { 'SMIME' => [] },
+        securityDefaultOptions: { 'SMIME' => [] },
+        value:                  { 'method' => 'SMIME', 'options' => [] },
+      }
 
 
       context 'with recipient certificate present' do
       context 'with recipient certificate present' do
         before do
         before do
           create(:smime_certificate, fixture: recipient_email_address)
           create(:smime_certificate, fixture: recipient_email_address)
         end
         end
 
 
-        it_behaves_like 'resolving security field', expected_result: { securityAllowed: { 'SMIME'=>['encryption'] }, value: { 'method' => 'SMIME', 'options' => ['encryption'] } }
+        it_behaves_like 'resolving security field', expected_result: {
+          securityAllowed:        { 'SMIME'=>['encryption'] },
+          securityDefaultOptions: { 'SMIME' => ['encryption'] },
+          value:                  { 'method' => 'SMIME', 'options' => ['encryption'] },
+        }
       end
       end
 
 
       context 'when email address is invalid' do
       context 'when email address is invalid' do
         let(:recipient_email_address) { 'invalid-email-address' }
         let(:recipient_email_address) { 'invalid-email-address' }
 
 
-        it_behaves_like 'resolving security field', expected_result: { securityAllowed: { 'SMIME'=>[] }, value: { 'method' => 'SMIME', 'options' => [] } }
+        it_behaves_like 'resolving security field', expected_result: {
+          securityAllowed:        { 'SMIME' => [] },
+          securityDefaultOptions: { 'SMIME' => [] },
+          value:                  { 'method' => 'SMIME', 'options' => [] },
+        }
       end
       end
     end
     end
 
 
@@ -179,14 +202,22 @@ RSpec.shared_examples 'HasSecurityOptions' do |type:|
         end
         end
       end
       end
 
 
-      it_behaves_like 'resolving security field', expected_result: { securityAllowed: { 'SMIME'=>[] }, value: { 'method' => 'SMIME', 'options' => [] } }
+      it_behaves_like 'resolving security field', expected_result: {
+        securityAllowed:        { 'SMIME' => [] },
+        securityDefaultOptions: { 'SMIME' => [] },
+        value:                  { 'method' => 'SMIME', 'options' => [] },
+      }
 
 
       context 'with only one recipient certificate present' do
       context 'with only one recipient certificate present' do
         before do
         before do
           create(:smime_certificate, fixture: recipient_email_address1)
           create(:smime_certificate, fixture: recipient_email_address1)
         end
         end
 
 
-        it_behaves_like 'resolving security field', expected_result: { securityAllowed: { 'SMIME'=>[] }, value: { 'method' => 'SMIME', 'options' => [] } }
+        it_behaves_like 'resolving security field', expected_result: {
+          securityAllowed:        { 'SMIME' => [] },
+          securityDefaultOptions: { 'SMIME' => [] },
+          value:                  { 'method' => 'SMIME', 'options' => [] },
+        }
       end
       end
 
 
       context 'with both recipient certificates present' do
       context 'with both recipient certificates present' do
@@ -195,28 +226,44 @@ RSpec.shared_examples 'HasSecurityOptions' do |type:|
           create(:smime_certificate, fixture: recipient_email_address2)
           create(:smime_certificate, fixture: recipient_email_address2)
         end
         end
 
 
-        it_behaves_like 'resolving security field', expected_result: { securityAllowed: { 'SMIME'=>['encryption'] }, value: { 'method' => 'SMIME', 'options' => ['encryption'] } }
+        it_behaves_like 'resolving security field', expected_result: {
+          securityAllowed:        { 'SMIME' => ['encryption'] },
+          securityDefaultOptions: { 'SMIME' => ['encryption'] },
+          value:                  { 'method' => 'SMIME', 'options' => ['encryption'] },
+        }
       end
       end
     end
     end
 
 
     context 'with group present' do
     context 'with group present' do
       let(:data) { base_data.tap { |data| data['group_id'] = group.id } }
       let(:data) { base_data.tap { |data| data['group_id'] = group.id } }
 
 
-      it_behaves_like 'resolving security field', expected_result: { securityAllowed: { 'SMIME'=>[] }, value: { 'method' => 'SMIME', 'options' => [] } }
+      it_behaves_like 'resolving security field', expected_result: {
+        securityAllowed:        { 'SMIME' => [] },
+        securityDefaultOptions: { 'SMIME' => [] },
+        value:                  { 'method' => 'SMIME', 'options' => [] },
+      }
 
 
       context 'when the group has a configured sender address' do
       context 'when the group has a configured sender address' do
         let(:system_email_address) { 'smime1@example.com' }
         let(:system_email_address) { 'smime1@example.com' }
         let(:email_address)        { create(:email_address, email: system_email_address) }
         let(:email_address)        { create(:email_address, email: system_email_address) }
         let(:group)                { create(:group, email_address: email_address) }
         let(:group)                { create(:group, email_address: email_address) }
 
 
-        it_behaves_like 'resolving security field', expected_result: { securityAllowed: { 'SMIME'=>[] }, value: { 'method' => 'SMIME', 'options' => [] } }
+        it_behaves_like 'resolving security field', expected_result: {
+          securityAllowed:        { 'SMIME' => [] },
+          securityDefaultOptions: { 'SMIME' => [] },
+          value:                  { 'method' => 'SMIME', 'options' => [] },
+        }
 
 
         context 'with sender certificate present' do
         context 'with sender certificate present' do
           before do
           before do
             create(:smime_certificate, :with_private, fixture: system_email_address)
             create(:smime_certificate, :with_private, fixture: system_email_address)
           end
           end
 
 
-          it_behaves_like 'resolving security field', expected_result: { securityAllowed: { 'SMIME'=>['sign'] }, value: { 'method' => 'SMIME', 'options' => ['sign'] } }
+          it_behaves_like 'resolving security field', expected_result: {
+            securityAllowed:        { 'SMIME'=>['sign'] },
+            securityDefaultOptions: { 'SMIME' => ['sign'] },
+            value:                  { 'method' => 'SMIME', 'options' => ['sign'] },
+          }
         end
         end
       end
       end
     end
     end
@@ -240,7 +287,11 @@ RSpec.shared_examples 'HasSecurityOptions' do |type:|
         end
         end
       end
       end
 
 
-      it_behaves_like 'resolving security field', expected_result: { securityAllowed: { 'SMIME'=>[] }, value: { 'method' => 'SMIME', 'options' => [] } }
+      it_behaves_like 'resolving security field', expected_result: {
+        securityAllowed:        { 'SMIME' => [] },
+        securityDefaultOptions: { 'SMIME' => [] },
+        value:                  { 'method' => 'SMIME', 'options' => [] },
+      }
 
 
       context 'with recipient and sender certificates present' do
       context 'with recipient and sender certificates present' do
         before do
         before do
@@ -248,7 +299,11 @@ RSpec.shared_examples 'HasSecurityOptions' do |type:|
           create(:smime_certificate, :with_private, fixture: system_email_address)
           create(:smime_certificate, :with_private, fixture: system_email_address)
         end
         end
 
 
-        it_behaves_like 'resolving security field', expected_result: { securityAllowed: { 'SMIME'=>%w[sign encryption] }, value: { 'method' => 'SMIME', 'options' => %w[sign encryption] } }
+        it_behaves_like 'resolving security field', expected_result: {
+          securityAllowed:        { 'SMIME' => %w[sign encryption] },
+          securityDefaultOptions: { 'SMIME' => %w[sign encryption] },
+          value:                  { 'method' => 'SMIME', 'options' => %w[sign encryption] },
+        }
 
 
         context 'with default group configuration' do
         context 'with default group configuration' do
           let(:smime_config) do
           let(:smime_config) do
@@ -269,31 +324,46 @@ RSpec.shared_examples 'HasSecurityOptions' do |type:|
           let(:default_encryption) { true }
           let(:default_encryption) { true }
           let(:default_sign)       { true }
           let(:default_sign)       { true }
 
 
-          it_behaves_like 'resolving security field', expected_result: { value: { 'method' => 'SMIME', 'options' => %w[sign encryption] } }
+          it_behaves_like 'resolving security field', expected_result: {
+            securityDefaultOptions: { 'SMIME' => %w[sign encryption] },
+            value:                  { 'method' => 'SMIME', 'options' => %w[sign encryption] }
+          }
 
 
           context 'when it has no value' do
           context 'when it has no value' do
             let(:group_defaults) { {} }
             let(:group_defaults) { {} }
 
 
-            it_behaves_like 'resolving security field', expected_result: { value: { 'method' => 'SMIME', 'options' => %w[sign encryption] } }
+            it_behaves_like 'resolving security field', expected_result: {
+              securityDefaultOptions: { 'SMIME' => %w[sign encryption] },
+              value:                  { 'method' => 'SMIME', 'options' => %w[sign encryption] },
+            }
           end
           end
 
 
           context 'when encryption is disabled' do
           context 'when encryption is disabled' do
             let(:default_encryption) { false }
             let(:default_encryption) { false }
 
 
-            it_behaves_like 'resolving security field', expected_result: { value: { 'method' => 'SMIME', 'options' => ['sign'] } }
+            it_behaves_like 'resolving security field', expected_result: {
+              securityDefaultOptions: { 'SMIME' => ['sign'] },
+              value:                  { 'method' => 'SMIME', 'options' => ['sign'] },
+            }
           end
           end
 
 
           context 'when signing is disabled' do
           context 'when signing is disabled' do
             let(:default_sign) { false }
             let(:default_sign) { false }
 
 
-            it_behaves_like 'resolving security field', expected_result: { value: { 'method' => 'SMIME', 'options' => ['encryption'] } }
+            it_behaves_like 'resolving security field', expected_result: {
+              securityDefaultOptions: { 'SMIME' => ['encryption'] },
+              value:                  { 'method' => 'SMIME', 'options' => ['encryption'] },
+            }
           end
           end
 
 
           context 'when both encryption and signing are disabled' do
           context 'when both encryption and signing are disabled' do
             let(:default_encryption) { false }
             let(:default_encryption) { false }
             let(:default_sign)       { false }
             let(:default_sign)       { false }
 
 
-            it_behaves_like 'resolving security field', expected_result: { value: { 'method' => 'SMIME', 'options' => [] } }
+            it_behaves_like 'resolving security field', expected_result: {
+              securityDefaultOptions: { 'SMIME' => [] },
+              value:                  { 'method' => 'SMIME', 'options' => [] },
+            }
           end
           end
         end
         end
       end
       end