1<template>
2  <b-modal
3    id="modal-settings"
4    ref="modal"
5    :title="$t('pageUserManagement.accountPolicySettings')"
6    @hidden="resetForm"
7  >
8    <b-form id="form-settings" novalidate @submit.prevent="handleSubmit">
9      <b-container>
10        <b-row>
11          <b-col>
12            <b-form-group
13              :label="$t('pageUserManagement.modal.maxFailedLoginAttempts')"
14              label-for="lockout-threshold"
15            >
16              <b-form-text id="lockout-threshold-help-block">
17                {{
18                  $t('global.form.valueMustBeBetween', {
19                    min: 0,
20                    max: 65535,
21                  })
22                }}
23              </b-form-text>
24              <b-form-input
25                id="lockout-threshold"
26                v-model.number="form.lockoutThreshold"
27                type="number"
28                aria-describedby="lockout-threshold-help-block"
29                data-test-id="userManagement-input-lockoutThreshold"
30                :state="getValidationState(v$.form.lockoutThreshold)"
31                @input="v$.form.lockoutThreshold.$touch()"
32              />
33              <b-form-invalid-feedback role="alert">
34                <template v-if="v$.form.lockoutThreshold.required.$invalid">
35                  {{ $t('global.form.fieldRequired') }}
36                </template>
37                <template
38                  v-else-if="
39                    !v$.form.lockoutThreshold.minLength ||
40                    !v$.form.lockoutThreshold.maxLength
41                  "
42                >
43                  {{
44                    $t('global.form.valueMustBeBetween', {
45                      min: 0,
46                      max: 65535,
47                    })
48                  }}
49                </template>
50              </b-form-invalid-feedback>
51            </b-form-group>
52          </b-col>
53          <b-col>
54            <b-form-group
55              :label="$t('pageUserManagement.modal.userUnlockMethod')"
56            >
57              <b-form-radio
58                v-model="form.unlockMethod"
59                name="unlock-method"
60                class="mb-2"
61                :value="0"
62                data-test-id="userManagement-radio-manualUnlock"
63                @input="v$.form.unlockMethod.$touch()"
64              >
65                {{ $t('pageUserManagement.modal.manual') }}
66              </b-form-radio>
67              <b-form-radio
68                v-model="form.unlockMethod"
69                name="unlock-method"
70                :value="1"
71                data-test-id="userManagement-radio-automaticUnlock"
72                @input="v$.form.unlockMethod.$touch()"
73              >
74                {{ $t('pageUserManagement.modal.automaticAfterTimeout') }}
75              </b-form-radio>
76              <div class="mt-3 ml-4">
77                <b-form-text id="lockout-duration-help-block">
78                  {{ $t('pageUserManagement.modal.timeoutDurationSeconds') }}
79                </b-form-text>
80                <b-form-input
81                  v-model.number="form.lockoutDuration"
82                  aria-describedby="lockout-duration-help-block"
83                  type="number"
84                  data-test-id="userManagement-input-lockoutDuration"
85                  :state="getValidationState(v$.form.lockoutDuration)"
86                  :readonly="v$.form.unlockMethod.$model === 0"
87                  @input="v$.form.lockoutDuration.$touch()"
88                />
89                <b-form-invalid-feedback role="alert">
90                  <template v-if="v$.form.lockoutDuration.required.$invalid">
91                    {{ $t('global.form.fieldRequired') }}
92                  </template>
93                  <template v-else-if="!v$.form.lockoutDuration.minvalue">
94                    {{ $t('global.form.mustBeAtLeast', { value: 1 }) }}
95                  </template>
96                </b-form-invalid-feedback>
97              </div>
98            </b-form-group>
99          </b-col>
100        </b-row>
101      </b-container>
102    </b-form>
103    <template #modal-footer="{ cancel }">
104      <b-button
105        variant="secondary"
106        data-test-id="userManagement-button-cancel"
107        @click="cancel()"
108      >
109        {{ $t('global.action.cancel') }}
110      </b-button>
111      <b-button
112        form="form-settings"
113        type="submit"
114        variant="primary"
115        data-test-id="userManagement-button-submit"
116        @click="onOk"
117      >
118        {{ $t('global.action.save') }}
119      </b-button>
120    </template>
121  </b-modal>
122</template>
123
124<script>
125import VuelidateMixin from '@/components/Mixins/VuelidateMixin.js';
126import { useVuelidate } from '@vuelidate/core';
127import { useI18n } from 'vue-i18n';
128
129import {
130  required,
131  requiredIf,
132  minValue,
133  maxValue,
134} from '@vuelidate/validators';
135
136export default {
137  mixins: [VuelidateMixin],
138  props: {
139    settings: {
140      type: Object,
141      required: true,
142    },
143  },
144  setup() {
145    return {
146      v$: useVuelidate(),
147    };
148  },
149  data() {
150    return {
151      $t: useI18n().t,
152      form: {
153        lockoutThreshold: 0,
154        unlockMethod: 0,
155        lockoutDuration: null,
156      },
157    };
158  },
159  watch: {
160    settings: function ({ lockoutThreshold, lockoutDuration }) {
161      this.form.lockoutThreshold = lockoutThreshold;
162      this.form.unlockMethod = lockoutDuration ? 1 : 0;
163      this.form.lockoutDuration = lockoutDuration ? lockoutDuration : null;
164    },
165  },
166  validations: {
167    form: {
168      lockoutThreshold: {
169        minValue: minValue(0),
170        maxValue: maxValue(65535),
171        required,
172      },
173      unlockMethod: { required },
174      lockoutDuration: {
175        minValue: function (value) {
176          return this.form.unlockMethod === 0 || value > 0;
177        },
178        required: requiredIf(function () {
179          return this.form.unlockMethod === 1;
180        }),
181      },
182    },
183  },
184  methods: {
185    handleSubmit() {
186      this.v$.$touch();
187      if (this.v$.$invalid) return;
188
189      let lockoutThreshold;
190      let lockoutDuration;
191      if (this.v$.form.lockoutThreshold.$dirty) {
192        lockoutThreshold = this.form.lockoutThreshold;
193      }
194      if (this.v$.form.unlockMethod.$dirty) {
195        lockoutDuration = this.form.unlockMethod
196          ? this.form.lockoutDuration
197          : 0;
198      }
199
200      this.$emit('ok', { lockoutThreshold, lockoutDuration });
201      this.closeModal();
202    },
203    onOk(bvModalEvt) {
204      // prevent modal close
205      bvModalEvt.preventDefault();
206      this.handleSubmit();
207    },
208    closeModal() {
209      this.$nextTick(() => {
210        this.$refs.modal.hide();
211      });
212    },
213    resetForm() {
214      // Reset form models
215      this.form.lockoutThreshold = this.settings.lockoutThreshold;
216      this.form.unlockMethod = this.settings.lockoutDuration ? 1 : 0;
217      this.form.lockoutDuration = this.settings.lockoutDuration
218        ? this.settings.lockoutDuration
219        : null;
220      this.v$.$reset(); // clear validations
221    },
222  },
223};
224</script>
225