@adminforth/two-factors-auth 1.0.21 → 1.0.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/Changelog.md CHANGED
@@ -1,3 +1,8 @@
1
+ ## [1.0.19] - 2024-12-02
2
+
3
+ ### Fixed
4
+
5
+ - Fixed copy hash for 2fa
1
6
 
2
7
  ## [1.0.18] - 2024-09-13
3
8
 
@@ -13,25 +13,22 @@
13
13
  <!-- Modal content -->
14
14
  <div class="relative bg-white rounded-lg shadow dark:bg-gray-700 dark:shadow-black text-gray-500" >
15
15
  <div class="p-8 w-full max-w-md max-h-full" >
16
- <div class="m-3" >Please enter your authenticator code </div>
16
+ <div class="m-3">Please enter your authenticator code </div>
17
17
  <div class="my-4 flex justify-center items-center">
18
18
  <v-otp-input
19
19
  ref="code"
20
- input-classes="h-10 w-10 border border-[2px] rounded-md flex otp-input dark:bg-gray-700 dark:text-gray-400 font-bold"
20
+ input-classes="bg-gray-50 text-center flex justify-center otp-input border leading-none border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-10 h-10 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
21
21
  :conditionalClass="['one', 'two', 'three', 'four', 'five', 'six']"
22
22
  inputType="number"
23
23
  :num-inputs="6"
24
24
  v-model:value="bindValue"
25
25
  :should-auto-focus="true"
26
26
  :should-focus-order="true"
27
- @on-change="handleOnChange"
28
27
  @on-complete="handleOnComplete"
29
28
  />
30
29
  </div>
31
30
  <!-- <Vue2FACodeInput v-model="code"/> -->
32
- <button @click="()=>{router.push('./login')}" class="flex items-center justify-center gap-1 w-full text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800">
33
- Cancel
34
- </button>
31
+ <Button @click="() => {router.push('./login')}" class="w-full">Cancel</Button>
35
32
  </div>
36
33
  </div>
37
34
  </div>
@@ -52,6 +49,7 @@
52
49
  import { callAdminForthApi, loadFile } from '@/utils';
53
50
  import { useRouter } from 'vue-router';
54
51
  import { showErrorTost } from '@/composables/useFrontendApi';
52
+ import { Button } from '@/afcl';
55
53
  import Vue2FACodeInput from '@loltech/vue3-2fa-code-input';
56
54
  import VOtpInput from "vue3-otp-input";
57
55
 
@@ -99,13 +97,12 @@
99
97
 
100
98
  onMounted(async () => {
101
99
  coreStore.getPublicConfig();
102
- window.addEventListener('keydown', handleKeydown);
100
+ window.addEventListener('paste', handlePaste);
103
101
  });
104
102
 
105
103
  onBeforeUnmount(() => {
106
- window.removeEventListener('keydown', handleKeydown);
104
+ window.removeEventListener('paste', handlePaste);
107
105
  });
108
-
109
106
 
110
107
  async function sendCode (value) {
111
108
  inProgress.value = true;
@@ -130,16 +127,14 @@
130
127
  // }
131
128
  // })
132
129
 
133
- function handleKeydown(event) {
134
- if ((event.ctrlKey || event.metaKey) && event.key === 'v') {
135
- event.preventDefault();
136
- navigator.clipboard.readText().then((pastedData) => {
137
- if (pastedData) {
138
- fillInput(pastedData);
139
- }
140
- }).catch(err => {
141
- console.error('Failed to read clipboard contents: ', err);
142
- });
130
+ function handlePaste(event) {
131
+ event.preventDefault();
132
+ if (event.target.classList.contains('otp-input')) {
133
+ return;
134
+ }
135
+ const pastedText = event.clipboardData?.getData('text') || '';
136
+ if (pastedText.length === 6) {
137
+ code.value?.fillInput(pastedText);
143
138
  }
144
139
  }
145
140
  </script>
@@ -22,15 +22,15 @@
22
22
  <div class="w-full max-w-[46rem]">
23
23
  <div class="relative">
24
24
  <label for="npm-install-copy-text" class="sr-only">Label</label>
25
- <input id="npm-install-copy-text" type="text" class="col-span-10 bg-gray-50 border border-gray-300 text-gray-500 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full px-2.5 py-4 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-gray-400 dark:focus:ring-blue-500 dark:focus:border-blue-500" :value="totp.newSecret" disabled readonly>
26
- <button data-copy-to-clipboard-target="npm-install-copy-text" class="absolute end-2.5 top-1/2 -translate-y-1/2 text-gray-900 dark:text-gray-400 hover:bg-gray-100 dark:bg-gray-800 dark:border-gray-600 dark:hover:bg-gray-700 rounded-lg py-2 px-2.5 inline-flex items-center justify-center bg-white border-gray-200 border">
27
- <span id="default-message" class="inline-flex items-center">
25
+ <input id="npm-install-copy-text" type="text" class="col-span-10 bg-gray-50 border border-gray-300 text-gray-500 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full px-2.5 py-4 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-gray-400 dark:focus:ring-blue-500 dark:focus:border-blue-500 pr-20" :value="totp.newSecret" readonly>
26
+ <button @click="onCopyClick" data-copy-to-clipboard-target="npm-install-copy-text" class="absolute end-2.5 top-1/2 -translate-y-1/2 text-gray-900 dark:text-gray-400 hover:bg-gray-100 dark:bg-gray-800 dark:border-gray-600 dark:hover:bg-gray-700 rounded-lg py-2 px-2.5 inline-flex items-center justify-center bg-white border-gray-200 border">
27
+ <span v-if="isCopied === false" id="default-message" class="inline-flex items-center">
28
28
  <svg class="w-3 h-3 me-1.5" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 18 20">
29
29
  <path d="M16 1h-3.278A1.992 1.992 0 0 0 11 0H7a1.993 1.993 0 0 0-1.722 1H2a2 2 0 0 0-2 2v15a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V3a2 2 0 0 0-2-2Zm-3 14H5a1 1 0 0 1 0-2h8a1 1 0 0 1 0 2Zm0-4H5a1 1 0 0 1 0-2h8a1 1 0 1 1 0 2Zm0-5H5a1 1 0 0 1 0-2h2V2h4v2h2a1 1 0 1 1 0 2Z"/>
30
30
  </svg>
31
- <span @click="onCopyClick" class="text-xs font-semibold">Copy</span>
31
+ <span class="text-xs font-semibold">Copy</span>
32
32
  </span>
33
- <span id="success-message" class="hidden inline-flex items-center">
33
+ <span v-if="isCopied === true" id="success-message" class="inline-flex items-center">
34
34
  <svg class="w-3 h-3 text-lightPrimary dark:text-darkPrimary me-1.5" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 16 12">
35
35
  <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M1 5.917 5.724 10.5 15 1.5"/>
36
36
  </svg>
@@ -43,7 +43,7 @@
43
43
  <div class="my-4 flex justify-center items-center">
44
44
  <v-otp-input
45
45
  ref="code"
46
- input-classes="h-10 w-10 border border-[2px] rounded-md flex otp-input dark:bg-gray-700 dark:text-gray-400 font-bold"
46
+ input-classes="bg-gray-50 text-center flex justify-center otp-input border leading-none border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-10 h-10 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
47
47
  :conditionalClass="['one', 'two', 'three', 'four', 'five', 'six']"
48
48
  inputType="number"
49
49
  :num-inputs="6"
@@ -52,21 +52,21 @@
52
52
  @on-complete="handleOnComplete"
53
53
  />
54
54
  </div>
55
-
56
55
  <!-- <Vue2FACodeInput v-model="code" autofocus /> -->
57
- <button @click="()=>{router.push('./login')}" class="flex items-center justify-center gap-1 w-full text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800">Cancel</button>
56
+ <Button @click="()=>{router.push('./login')}"
57
+ class="w-full">Cancel
58
+ </Button>
58
59
  </div>
59
60
  </div>
60
61
  </div>
61
62
  </div>
62
-
63
- </div>
63
+ </div>
64
64
 
65
65
 
66
66
  </template>
67
67
 
68
68
 
69
- <script setup>
69
+ <script setup lang="ts">
70
70
 
71
71
  import { onMounted, onBeforeUnmount, ref, watchEffect,computed,watch } from 'vue';
72
72
  import { useCoreStore } from '@/stores/core';
@@ -75,18 +75,16 @@ import { IconEyeSolid, IconEyeSlashSolid } from '@iconify-prerendered/vue-flowbi
75
75
  import { callAdminForthApi, loadFile } from '@/utils';
76
76
  import { useRouter } from 'vue-router';
77
77
  import { showErrorTost } from '@/composables/useFrontendApi';
78
+ import { Button } from '@/afcl';
78
79
  import Vue2FACodeInput from '@loltech/vue3-2fa-code-input';
79
80
  import VOtpInput from "vue3-otp-input";
80
81
 
81
82
  const code = ref(null);
83
+ const isCopied = ref<boolean>(false);
82
84
  const handleOnComplete = (value) => {
83
85
  sendCode(value);
84
86
  };
85
87
 
86
- const fillInput = (value) => {
87
- code.value?.fillInput(value);
88
- };
89
-
90
88
  const router = useRouter();
91
89
  const inProgress = ref(false);
92
90
 
@@ -95,9 +93,6 @@ const user = useUserStore();
95
93
 
96
94
  // use this simple function to automatically focus on the next input
97
95
 
98
-
99
-
100
-
101
96
  const showPw = ref(false);
102
97
 
103
98
  const error = ref(null);
@@ -127,16 +122,11 @@ function parseJwt(token) {
127
122
  }
128
123
 
129
124
  function onCopyClick(){
125
+ isCopied.value = true;
126
+ navigator.clipboard.writeText(totp.value.newSecret);
130
127
  window.adminforth.alert({message: 'Copied to clipboard', variant: 'success'})
131
128
  }
132
129
 
133
- // watch(code, async (nv)=>{
134
- // if (nv){
135
- // console.log(code.value);
136
- // sendCode();
137
- // }
138
- // })
139
-
140
130
  onMounted(async () => {
141
131
  coreStore.getPublicConfig()
142
132
  const resp = await callAdminForthApi({
@@ -149,11 +139,12 @@ onMounted(async () => {
149
139
 
150
140
  totp.value=parseJwt(totpJWT.value);
151
141
 
152
- window.addEventListener('keydown', handleKeydown);
142
+
143
+ window.addEventListener('paste', handlePaste);
153
144
  });
154
145
 
155
146
  onBeforeUnmount(() => {
156
- window.removeEventListener('keydown', handleKeydown);
147
+ window.removeEventListener('paste', handlePaste);
157
148
  });
158
149
 
159
150
  async function sendCode (value) {
@@ -176,22 +167,19 @@ async function sendCode (value) {
176
167
  }
177
168
 
178
169
 
179
- function handleKeydown(event) {
180
- if ((event.ctrlKey || event.metaKey) && event.key === 'v') {
181
- event.preventDefault();
182
- navigator.clipboard.readText().then((pastedData) => {
183
- if (pastedData) {
184
- fillInput(pastedData);
185
- }
186
- }).catch(err => {
187
- console.error('Failed to read clipboard contents: ', err);
188
- });
170
+ function handlePaste(event) {
171
+ event.preventDefault();
172
+ if (event.target.classList.contains('otp-input')) {
173
+ return;
174
+ }
175
+ const pastedText = event.clipboardData?.getData('text') || '';
176
+ if (pastedText.length === 6) {
177
+ code.value?.fillInput(pastedText);
189
178
  }
190
179
  }
191
180
  </script>
192
181
  <style>
193
182
  .otp-input {
194
183
  margin: 0 5px;
195
-
196
184
  }
197
185
  </style>
@@ -13,25 +13,22 @@
13
13
  <!-- Modal content -->
14
14
  <div class="relative bg-white rounded-lg shadow dark:bg-gray-700 dark:shadow-black text-gray-500" >
15
15
  <div class="p-8 w-full max-w-md max-h-full" >
16
- <div class="m-3" >Please enter your authenticator code </div>
16
+ <div class="m-3">Please enter your authenticator code </div>
17
17
  <div class="my-4 flex justify-center items-center">
18
18
  <v-otp-input
19
19
  ref="code"
20
- input-classes="h-10 w-10 border border-[2px] rounded-md flex otp-input dark:bg-gray-700 dark:text-gray-400 font-bold"
20
+ input-classes="bg-gray-50 text-center flex justify-center otp-input border leading-none border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-10 h-10 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
21
21
  :conditionalClass="['one', 'two', 'three', 'four', 'five', 'six']"
22
22
  inputType="number"
23
23
  :num-inputs="6"
24
24
  v-model:value="bindValue"
25
25
  :should-auto-focus="true"
26
26
  :should-focus-order="true"
27
- @on-change="handleOnChange"
28
27
  @on-complete="handleOnComplete"
29
28
  />
30
29
  </div>
31
30
  <!-- <Vue2FACodeInput v-model="code"/> -->
32
- <button @click="()=>{router.push('./login')}" class="flex items-center justify-center gap-1 w-full text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800">
33
- Cancel
34
- </button>
31
+ <Button @click="() => {router.push('./login')}" class="w-full">Cancel</Button>
35
32
  </div>
36
33
  </div>
37
34
  </div>
@@ -52,6 +49,7 @@
52
49
  import { callAdminForthApi, loadFile } from '@/utils';
53
50
  import { useRouter } from 'vue-router';
54
51
  import { showErrorTost } from '@/composables/useFrontendApi';
52
+ import { Button } from '@/afcl';
55
53
  import Vue2FACodeInput from '@loltech/vue3-2fa-code-input';
56
54
  import VOtpInput from "vue3-otp-input";
57
55
 
@@ -99,13 +97,12 @@
99
97
 
100
98
  onMounted(async () => {
101
99
  coreStore.getPublicConfig();
102
- window.addEventListener('keydown', handleKeydown);
100
+ window.addEventListener('paste', handlePaste);
103
101
  });
104
102
 
105
103
  onBeforeUnmount(() => {
106
- window.removeEventListener('keydown', handleKeydown);
104
+ window.removeEventListener('paste', handlePaste);
107
105
  });
108
-
109
106
 
110
107
  async function sendCode (value) {
111
108
  inProgress.value = true;
@@ -130,16 +127,14 @@
130
127
  // }
131
128
  // })
132
129
 
133
- function handleKeydown(event) {
134
- if ((event.ctrlKey || event.metaKey) && event.key === 'v') {
135
- event.preventDefault();
136
- navigator.clipboard.readText().then((pastedData) => {
137
- if (pastedData) {
138
- fillInput(pastedData);
139
- }
140
- }).catch(err => {
141
- console.error('Failed to read clipboard contents: ', err);
142
- });
130
+ function handlePaste(event) {
131
+ event.preventDefault();
132
+ if (event.target.classList.contains('otp-input')) {
133
+ return;
134
+ }
135
+ const pastedText = event.clipboardData?.getData('text') || '';
136
+ if (pastedText.length === 6) {
137
+ code.value?.fillInput(pastedText);
143
138
  }
144
139
  }
145
140
  </script>
@@ -22,15 +22,15 @@
22
22
  <div class="w-full max-w-[46rem]">
23
23
  <div class="relative">
24
24
  <label for="npm-install-copy-text" class="sr-only">Label</label>
25
- <input id="npm-install-copy-text" type="text" class="col-span-10 bg-gray-50 border border-gray-300 text-gray-500 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full px-2.5 py-4 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-gray-400 dark:focus:ring-blue-500 dark:focus:border-blue-500" :value="totp.newSecret" disabled readonly>
26
- <button data-copy-to-clipboard-target="npm-install-copy-text" class="absolute end-2.5 top-1/2 -translate-y-1/2 text-gray-900 dark:text-gray-400 hover:bg-gray-100 dark:bg-gray-800 dark:border-gray-600 dark:hover:bg-gray-700 rounded-lg py-2 px-2.5 inline-flex items-center justify-center bg-white border-gray-200 border">
27
- <span id="default-message" class="inline-flex items-center">
25
+ <input id="npm-install-copy-text" type="text" class="col-span-10 bg-gray-50 border border-gray-300 text-gray-500 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full px-2.5 py-4 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-gray-400 dark:focus:ring-blue-500 dark:focus:border-blue-500 pr-20" :value="totp.newSecret" readonly>
26
+ <button @click="onCopyClick" data-copy-to-clipboard-target="npm-install-copy-text" class="absolute end-2.5 top-1/2 -translate-y-1/2 text-gray-900 dark:text-gray-400 hover:bg-gray-100 dark:bg-gray-800 dark:border-gray-600 dark:hover:bg-gray-700 rounded-lg py-2 px-2.5 inline-flex items-center justify-center bg-white border-gray-200 border">
27
+ <span v-if="isCopied === false" id="default-message" class="inline-flex items-center">
28
28
  <svg class="w-3 h-3 me-1.5" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 18 20">
29
29
  <path d="M16 1h-3.278A1.992 1.992 0 0 0 11 0H7a1.993 1.993 0 0 0-1.722 1H2a2 2 0 0 0-2 2v15a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V3a2 2 0 0 0-2-2Zm-3 14H5a1 1 0 0 1 0-2h8a1 1 0 0 1 0 2Zm0-4H5a1 1 0 0 1 0-2h8a1 1 0 1 1 0 2Zm0-5H5a1 1 0 0 1 0-2h2V2h4v2h2a1 1 0 1 1 0 2Z"/>
30
30
  </svg>
31
- <span @click="onCopyClick" class="text-xs font-semibold">Copy</span>
31
+ <span class="text-xs font-semibold">Copy</span>
32
32
  </span>
33
- <span id="success-message" class="hidden inline-flex items-center">
33
+ <span v-if="isCopied === true" id="success-message" class="inline-flex items-center">
34
34
  <svg class="w-3 h-3 text-lightPrimary dark:text-darkPrimary me-1.5" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 16 12">
35
35
  <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M1 5.917 5.724 10.5 15 1.5"/>
36
36
  </svg>
@@ -43,7 +43,7 @@
43
43
  <div class="my-4 flex justify-center items-center">
44
44
  <v-otp-input
45
45
  ref="code"
46
- input-classes="h-10 w-10 border border-[2px] rounded-md flex otp-input dark:bg-gray-700 dark:text-gray-400 font-bold"
46
+ input-classes="bg-gray-50 text-center flex justify-center otp-input border leading-none border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-10 h-10 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
47
47
  :conditionalClass="['one', 'two', 'three', 'four', 'five', 'six']"
48
48
  inputType="number"
49
49
  :num-inputs="6"
@@ -52,21 +52,21 @@
52
52
  @on-complete="handleOnComplete"
53
53
  />
54
54
  </div>
55
-
56
55
  <!-- <Vue2FACodeInput v-model="code" autofocus /> -->
57
- <button @click="()=>{router.push('./login')}" class="flex items-center justify-center gap-1 w-full text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800">Cancel</button>
56
+ <Button @click="()=>{router.push('./login')}"
57
+ class="w-full">Cancel
58
+ </Button>
58
59
  </div>
59
60
  </div>
60
61
  </div>
61
62
  </div>
62
-
63
- </div>
63
+ </div>
64
64
 
65
65
 
66
66
  </template>
67
67
 
68
68
 
69
- <script setup>
69
+ <script setup lang="ts">
70
70
 
71
71
  import { onMounted, onBeforeUnmount, ref, watchEffect,computed,watch } from 'vue';
72
72
  import { useCoreStore } from '@/stores/core';
@@ -75,18 +75,16 @@ import { IconEyeSolid, IconEyeSlashSolid } from '@iconify-prerendered/vue-flowbi
75
75
  import { callAdminForthApi, loadFile } from '@/utils';
76
76
  import { useRouter } from 'vue-router';
77
77
  import { showErrorTost } from '@/composables/useFrontendApi';
78
+ import { Button } from '@/afcl';
78
79
  import Vue2FACodeInput from '@loltech/vue3-2fa-code-input';
79
80
  import VOtpInput from "vue3-otp-input";
80
81
 
81
82
  const code = ref(null);
83
+ const isCopied = ref<boolean>(false);
82
84
  const handleOnComplete = (value) => {
83
85
  sendCode(value);
84
86
  };
85
87
 
86
- const fillInput = (value) => {
87
- code.value?.fillInput(value);
88
- };
89
-
90
88
  const router = useRouter();
91
89
  const inProgress = ref(false);
92
90
 
@@ -95,9 +93,6 @@ const user = useUserStore();
95
93
 
96
94
  // use this simple function to automatically focus on the next input
97
95
 
98
-
99
-
100
-
101
96
  const showPw = ref(false);
102
97
 
103
98
  const error = ref(null);
@@ -127,16 +122,11 @@ function parseJwt(token) {
127
122
  }
128
123
 
129
124
  function onCopyClick(){
125
+ isCopied.value = true;
126
+ navigator.clipboard.writeText(totp.value.newSecret);
130
127
  window.adminforth.alert({message: 'Copied to clipboard', variant: 'success'})
131
128
  }
132
129
 
133
- // watch(code, async (nv)=>{
134
- // if (nv){
135
- // console.log(code.value);
136
- // sendCode();
137
- // }
138
- // })
139
-
140
130
  onMounted(async () => {
141
131
  coreStore.getPublicConfig()
142
132
  const resp = await callAdminForthApi({
@@ -149,11 +139,12 @@ onMounted(async () => {
149
139
 
150
140
  totp.value=parseJwt(totpJWT.value);
151
141
 
152
- window.addEventListener('keydown', handleKeydown);
142
+
143
+ window.addEventListener('paste', handlePaste);
153
144
  });
154
145
 
155
146
  onBeforeUnmount(() => {
156
- window.removeEventListener('keydown', handleKeydown);
147
+ window.removeEventListener('paste', handlePaste);
157
148
  });
158
149
 
159
150
  async function sendCode (value) {
@@ -176,22 +167,19 @@ async function sendCode (value) {
176
167
  }
177
168
 
178
169
 
179
- function handleKeydown(event) {
180
- if ((event.ctrlKey || event.metaKey) && event.key === 'v') {
181
- event.preventDefault();
182
- navigator.clipboard.readText().then((pastedData) => {
183
- if (pastedData) {
184
- fillInput(pastedData);
185
- }
186
- }).catch(err => {
187
- console.error('Failed to read clipboard contents: ', err);
188
- });
170
+ function handlePaste(event) {
171
+ event.preventDefault();
172
+ if (event.target.classList.contains('otp-input')) {
173
+ return;
174
+ }
175
+ const pastedText = event.clipboardData?.getData('text') || '';
176
+ if (pastedText.length === 6) {
177
+ code.value?.fillInput(pastedText);
189
178
  }
190
179
  }
191
180
  </script>
192
181
  <style>
193
182
  .otp-input {
194
183
  margin: 0 5px;
195
-
196
184
  }
197
185
  </style>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adminforth/two-factors-auth",
3
- "version": "1.0.21",
3
+ "version": "1.0.28",
4
4
  "description": "AdminForth plugin for two factors authentication",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
File without changes
File without changes