@adminforth/two-factors-auth 1.0.17 → 1.0.19

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 ADDED
@@ -0,0 +1,6 @@
1
+
2
+ ## [1.0.18] - 2024-09-13
3
+
4
+ ### Added
5
+
6
+ - add usersFilterToApply to TwoFactorsAuthPlugin to disable 2FA for specific users
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <div class="relative flex items-center justify-center min-h-screen bg-gray-100 dark:bg-gray-800"
3
- :style="coreStore.config?.loginBackgroundImage ? {
3
+ :style="(coreStore.config?.loginBackgroundImage && coreStore.config?.loginBackgroundPosition === 'over') ? {
4
4
  'background-image': 'url(' + loadFile(coreStore.config?.loginBackgroundImage) + ')',
5
5
  'background-size': 'cover',
6
6
  'background-position': 'center',
@@ -14,7 +14,21 @@
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
16
  <div class="m-3" >Please enter your authenticator code </div>
17
- <Vue2FACodeInput v-model="code"/>
17
+ <div class="my-4 flex justify-center items-center">
18
+ <v-otp-input
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"
21
+ :conditionalClass="['one', 'two', 'three', 'four', 'five', 'six']"
22
+ inputType="number"
23
+ :num-inputs="6"
24
+ v-model:value="bindValue"
25
+ :should-auto-focus="true"
26
+ :should-focus-order="true"
27
+ @on-change="handleOnChange"
28
+ @on-complete="handleOnComplete"
29
+ />
30
+ </div>
31
+ <!-- <Vue2FACodeInput v-model="code"/> -->
18
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">
19
33
  Cancel
20
34
  </button>
@@ -31,17 +45,26 @@
31
45
 
32
46
  <script setup>
33
47
 
34
- import { onMounted, ref, watchEffect,computed,watch } from 'vue';
48
+ import { onMounted, onBeforeUnmount, ref, watchEffect,computed,watch } from 'vue';
35
49
  import { useCoreStore } from '@/stores/core';
36
50
  import { useUserStore } from '@/stores/user';
37
51
  import { IconEyeSolid, IconEyeSlashSolid } from '@iconify-prerendered/vue-flowbite';
38
52
  import { callAdminForthApi, loadFile } from '@/utils';
39
53
  import { useRouter } from 'vue-router';
40
- import { initFlowbite } from 'flowbite'
41
54
  import { showErrorTost } from '@/composables/useFrontendApi';
42
55
  import Vue2FACodeInput from '@loltech/vue3-2fa-code-input';
56
+ import VOtpInput from "vue3-otp-input";
43
57
 
44
58
  const code = ref(null);
59
+
60
+ const handleOnComplete = (value) => {
61
+ sendCode(value);
62
+ };
63
+
64
+ const fillInput = (value) => {
65
+ code.value?.fillInput(value);
66
+ };
67
+
45
68
  const router = useRouter();
46
69
  const inProgress = ref(false);
47
70
 
@@ -75,16 +98,22 @@
75
98
  }
76
99
 
77
100
  onMounted(async () => {
78
- coreStore.getPublicConfig()
101
+ coreStore.getPublicConfig();
102
+ window.addEventListener('keydown', handleKeydown);
79
103
  });
104
+
105
+ onBeforeUnmount(() => {
106
+ window.removeEventListener('keydown', handleKeydown);
107
+ });
108
+
80
109
 
81
- async function sendCode () {
110
+ async function sendCode (value) {
82
111
  inProgress.value = true;
83
112
  const resp = await callAdminForthApi({
84
113
  method: 'POST',
85
114
  path: '/plugin/twofa/confirmSetup',
86
115
  body: {
87
- code: code.value,
116
+ code: value,
88
117
  secret: null,
89
118
  }
90
119
  })
@@ -95,11 +124,24 @@
95
124
  }
96
125
  }
97
126
 
98
- watch(code, async (nv)=>{
99
- if (nv){
100
- sendCode();
127
+ // watch(code, async (nv)=>{
128
+ // if (nv){
129
+ // sendCode();
130
+ // }
131
+ // })
132
+
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
+ });
101
143
  }
102
- })
144
+ }
103
145
  </script>
104
146
 
105
147
  <style lang='scss'>
@@ -109,7 +151,9 @@
109
151
  gap: 1rem;
110
152
  margin-bottom: 1rem;
111
153
  }
112
-
154
+ .otp-input {
155
+ margin: 0 5px;
156
+ }
113
157
  .vue3-2fa-code-input-box {
114
158
  &[type='text'] {
115
159
  @apply w-10 h-10 text-center text-xl border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500;
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <div class="relative flex items-center justify-center min-h-screen bg-gray-100 dark:bg-gray-800"
3
- :style="coreStore.config?.loginBackgroundImage ? {
3
+ :style="coreStore.config?.loginBackgroundImage && coreStore.config?.loginBackgroundPosition === 'over' ? {
4
4
  'background-image': 'url(' + loadFile(coreStore.config?.loginBackgroundImage) + ')',
5
5
  'background-size': 'cover',
6
6
  'background-position': 'center',
@@ -40,7 +40,20 @@
40
40
  </div>
41
41
  </div>
42
42
  </div>
43
- <Vue2FACodeInput v-model="code"/>
43
+ <div class="my-4 flex justify-center items-center">
44
+ <v-otp-input
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"
47
+ :conditionalClass="['one', 'two', 'three', 'four', 'five', 'six']"
48
+ inputType="number"
49
+ :num-inputs="6"
50
+ :should-auto-focus="true"
51
+ :should-focus-order="true"
52
+ @on-complete="handleOnComplete"
53
+ />
54
+ </div>
55
+
56
+ <!-- <Vue2FACodeInput v-model="code" autofocus /> -->
44
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>
45
58
  </div>
46
59
  </div>
@@ -55,7 +68,7 @@
55
68
 
56
69
  <script setup>
57
70
 
58
- import { onMounted, ref, watchEffect,computed,watch } from 'vue';
71
+ import { onMounted, onBeforeUnmount, ref, watchEffect,computed,watch } from 'vue';
59
72
  import { useCoreStore } from '@/stores/core';
60
73
  import { useUserStore } from '@/stores/user';
61
74
  import { IconEyeSolid, IconEyeSlashSolid } from '@iconify-prerendered/vue-flowbite';
@@ -63,8 +76,16 @@ import { callAdminForthApi, loadFile } from '@/utils';
63
76
  import { useRouter } from 'vue-router';
64
77
  import { showErrorTost } from '@/composables/useFrontendApi';
65
78
  import Vue2FACodeInput from '@loltech/vue3-2fa-code-input';
79
+ import VOtpInput from "vue3-otp-input";
66
80
 
67
81
  const code = ref(null);
82
+ const handleOnComplete = (value) => {
83
+ sendCode(value);
84
+ };
85
+
86
+ const fillInput = (value) => {
87
+ code.value?.fillInput(value);
88
+ };
68
89
 
69
90
  const router = useRouter();
70
91
  const inProgress = ref(false);
@@ -76,6 +97,7 @@ const user = useUserStore();
76
97
 
77
98
 
78
99
 
100
+
79
101
  const showPw = ref(false);
80
102
 
81
103
  const error = ref(null);
@@ -108,11 +130,12 @@ function onCopyClick(){
108
130
  window.adminforth.alert({message: 'Copied to clipboard', variant: 'success'})
109
131
  }
110
132
 
111
- watch(code, async (nv)=>{
112
- if (nv){
113
- sendCode();
114
- }
115
- })
133
+ // watch(code, async (nv)=>{
134
+ // if (nv){
135
+ // console.log(code.value);
136
+ // sendCode();
137
+ // }
138
+ // })
116
139
 
117
140
  onMounted(async () => {
118
141
  coreStore.getPublicConfig()
@@ -126,16 +149,22 @@ onMounted(async () => {
126
149
 
127
150
  totp.value=parseJwt(totpJWT.value);
128
151
 
152
+ window.addEventListener('keydown', handleKeydown);
153
+ });
129
154
 
155
+ onBeforeUnmount(() => {
156
+ window.removeEventListener('keydown', handleKeydown);
130
157
  });
131
158
 
132
- async function sendCode () {
159
+ async function sendCode (value) {
133
160
  inProgress.value = true;
161
+
162
+
134
163
  const resp = await callAdminForthApi({
135
164
  method: 'POST',
136
165
  path: '/plugin/twofa/confirmSetup',
137
166
  body: {
138
- code: code.value,
167
+ code: value,
139
168
  secret: totp.value.newSecret,
140
169
  }
141
170
  })
@@ -145,4 +174,24 @@ async function sendCode () {
145
174
  showErrorTost('Invalid code');
146
175
  }
147
176
  }
177
+
178
+
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
+ });
189
+ }
190
+ }
148
191
  </script>
192
+ <style>
193
+ .otp-input {
194
+ margin: 0 5px;
195
+
196
+ }
197
+ </style>
@@ -9,13 +9,293 @@
9
9
  "version": "1.0.0",
10
10
  "license": "ISC",
11
11
  "dependencies": {
12
- "@loltech/vue3-2fa-code-input": "^1.1.0"
12
+ "@loltech/vue3-2fa-code-input": "^1.1.0",
13
+ "vue3-otp-input": "^0.5.21"
13
14
  }
14
15
  },
16
+ "node_modules/@babel/helper-string-parser": {
17
+ "version": "7.25.9",
18
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz",
19
+ "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==",
20
+ "license": "MIT",
21
+ "engines": {
22
+ "node": ">=6.9.0"
23
+ }
24
+ },
25
+ "node_modules/@babel/helper-validator-identifier": {
26
+ "version": "7.25.9",
27
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz",
28
+ "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==",
29
+ "license": "MIT",
30
+ "engines": {
31
+ "node": ">=6.9.0"
32
+ }
33
+ },
34
+ "node_modules/@babel/parser": {
35
+ "version": "7.25.9",
36
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.9.tgz",
37
+ "integrity": "sha512-aI3jjAAO1fh7vY/pBGsn1i9LDbRP43+asrRlkPuTXW5yHXtd1NgTEMudbBoDDxrf1daEEfPJqR+JBMakzrR4Dg==",
38
+ "license": "MIT",
39
+ "dependencies": {
40
+ "@babel/types": "^7.25.9"
41
+ },
42
+ "bin": {
43
+ "parser": "bin/babel-parser.js"
44
+ },
45
+ "engines": {
46
+ "node": ">=6.0.0"
47
+ }
48
+ },
49
+ "node_modules/@babel/types": {
50
+ "version": "7.25.9",
51
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.9.tgz",
52
+ "integrity": "sha512-OwS2CM5KocvQ/k7dFJa8i5bNGJP0hXWfVCfDkqRFP1IreH1JDC7wG6eCYCi0+McbfT8OR/kNqsI0UU0xP9H6PQ==",
53
+ "license": "MIT",
54
+ "dependencies": {
55
+ "@babel/helper-string-parser": "^7.25.9",
56
+ "@babel/helper-validator-identifier": "^7.25.9"
57
+ },
58
+ "engines": {
59
+ "node": ">=6.9.0"
60
+ }
61
+ },
62
+ "node_modules/@jridgewell/sourcemap-codec": {
63
+ "version": "1.5.0",
64
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
65
+ "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==",
66
+ "license": "MIT"
67
+ },
15
68
  "node_modules/@loltech/vue3-2fa-code-input": {
16
69
  "version": "1.1.0",
17
70
  "resolved": "https://registry.npmjs.org/@loltech/vue3-2fa-code-input/-/vue3-2fa-code-input-1.1.0.tgz",
18
71
  "integrity": "sha512-styyoQjsARSeVf6E5qMvYIVkLRrwYtfL8xDl5W+g9wKF8qlr2XGU2gi9maEg0X4Us41kJryXBzfRMUcv5tKIBA=="
72
+ },
73
+ "node_modules/@vue/compiler-core": {
74
+ "version": "3.5.12",
75
+ "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.12.tgz",
76
+ "integrity": "sha512-ISyBTRMmMYagUxhcpyEH0hpXRd/KqDU4ymofPgl2XAkY9ZhQ+h0ovEZJIiPop13UmR/54oA2cgMDjgroRelaEw==",
77
+ "license": "MIT",
78
+ "dependencies": {
79
+ "@babel/parser": "^7.25.3",
80
+ "@vue/shared": "3.5.12",
81
+ "entities": "^4.5.0",
82
+ "estree-walker": "^2.0.2",
83
+ "source-map-js": "^1.2.0"
84
+ }
85
+ },
86
+ "node_modules/@vue/compiler-dom": {
87
+ "version": "3.5.12",
88
+ "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.12.tgz",
89
+ "integrity": "sha512-9G6PbJ03uwxLHKQ3P42cMTi85lDRvGLB2rSGOiQqtXELat6uI4n8cNz9yjfVHRPIu+MsK6TE418Giruvgptckg==",
90
+ "license": "MIT",
91
+ "dependencies": {
92
+ "@vue/compiler-core": "3.5.12",
93
+ "@vue/shared": "3.5.12"
94
+ }
95
+ },
96
+ "node_modules/@vue/compiler-sfc": {
97
+ "version": "3.5.12",
98
+ "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.12.tgz",
99
+ "integrity": "sha512-2k973OGo2JuAa5+ZlekuQJtitI5CgLMOwgl94BzMCsKZCX/xiqzJYzapl4opFogKHqwJk34vfsaKpfEhd1k5nw==",
100
+ "license": "MIT",
101
+ "dependencies": {
102
+ "@babel/parser": "^7.25.3",
103
+ "@vue/compiler-core": "3.5.12",
104
+ "@vue/compiler-dom": "3.5.12",
105
+ "@vue/compiler-ssr": "3.5.12",
106
+ "@vue/shared": "3.5.12",
107
+ "estree-walker": "^2.0.2",
108
+ "magic-string": "^0.30.11",
109
+ "postcss": "^8.4.47",
110
+ "source-map-js": "^1.2.0"
111
+ }
112
+ },
113
+ "node_modules/@vue/compiler-ssr": {
114
+ "version": "3.5.12",
115
+ "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.12.tgz",
116
+ "integrity": "sha512-eLwc7v6bfGBSM7wZOGPmRavSWzNFF6+PdRhE+VFJhNCgHiF8AM7ccoqcv5kBXA2eWUfigD7byekvf/JsOfKvPA==",
117
+ "license": "MIT",
118
+ "dependencies": {
119
+ "@vue/compiler-dom": "3.5.12",
120
+ "@vue/shared": "3.5.12"
121
+ }
122
+ },
123
+ "node_modules/@vue/reactivity": {
124
+ "version": "3.5.12",
125
+ "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.12.tgz",
126
+ "integrity": "sha512-UzaN3Da7xnJXdz4Okb/BGbAaomRHc3RdoWqTzlvd9+WBR5m3J39J1fGcHes7U3za0ruYn/iYy/a1euhMEHvTAg==",
127
+ "license": "MIT",
128
+ "dependencies": {
129
+ "@vue/shared": "3.5.12"
130
+ }
131
+ },
132
+ "node_modules/@vue/runtime-core": {
133
+ "version": "3.5.12",
134
+ "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.12.tgz",
135
+ "integrity": "sha512-hrMUYV6tpocr3TL3Ad8DqxOdpDe4zuQY4HPY3X/VRh+L2myQO8MFXPAMarIOSGNu0bFAjh1yBkMPXZBqCk62Uw==",
136
+ "license": "MIT",
137
+ "dependencies": {
138
+ "@vue/reactivity": "3.5.12",
139
+ "@vue/shared": "3.5.12"
140
+ }
141
+ },
142
+ "node_modules/@vue/runtime-dom": {
143
+ "version": "3.5.12",
144
+ "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.12.tgz",
145
+ "integrity": "sha512-q8VFxR9A2MRfBr6/55Q3umyoN7ya836FzRXajPB6/Vvuv0zOPL+qltd9rIMzG/DbRLAIlREmnLsplEF/kotXKA==",
146
+ "license": "MIT",
147
+ "dependencies": {
148
+ "@vue/reactivity": "3.5.12",
149
+ "@vue/runtime-core": "3.5.12",
150
+ "@vue/shared": "3.5.12",
151
+ "csstype": "^3.1.3"
152
+ }
153
+ },
154
+ "node_modules/@vue/server-renderer": {
155
+ "version": "3.5.12",
156
+ "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.12.tgz",
157
+ "integrity": "sha512-I3QoeDDeEPZm8yR28JtY+rk880Oqmj43hreIBVTicisFTx/Dl7JpG72g/X7YF8hnQD3IFhkky5i2bPonwrTVPg==",
158
+ "license": "MIT",
159
+ "dependencies": {
160
+ "@vue/compiler-ssr": "3.5.12",
161
+ "@vue/shared": "3.5.12"
162
+ },
163
+ "peerDependencies": {
164
+ "vue": "3.5.12"
165
+ }
166
+ },
167
+ "node_modules/@vue/shared": {
168
+ "version": "3.5.12",
169
+ "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.12.tgz",
170
+ "integrity": "sha512-L2RPSAwUFbgZH20etwrXyVyCBu9OxRSi8T/38QsvnkJyvq2LufW2lDCOzm7t/U9C1mkhJGWYfCuFBCmIuNivrg==",
171
+ "license": "MIT"
172
+ },
173
+ "node_modules/csstype": {
174
+ "version": "3.1.3",
175
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
176
+ "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
177
+ "license": "MIT"
178
+ },
179
+ "node_modules/entities": {
180
+ "version": "4.5.0",
181
+ "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
182
+ "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
183
+ "license": "BSD-2-Clause",
184
+ "engines": {
185
+ "node": ">=0.12"
186
+ },
187
+ "funding": {
188
+ "url": "https://github.com/fb55/entities?sponsor=1"
189
+ }
190
+ },
191
+ "node_modules/estree-walker": {
192
+ "version": "2.0.2",
193
+ "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
194
+ "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
195
+ "license": "MIT"
196
+ },
197
+ "node_modules/magic-string": {
198
+ "version": "0.30.12",
199
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.12.tgz",
200
+ "integrity": "sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw==",
201
+ "license": "MIT",
202
+ "dependencies": {
203
+ "@jridgewell/sourcemap-codec": "^1.5.0"
204
+ }
205
+ },
206
+ "node_modules/nanoid": {
207
+ "version": "3.3.7",
208
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
209
+ "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
210
+ "funding": [
211
+ {
212
+ "type": "github",
213
+ "url": "https://github.com/sponsors/ai"
214
+ }
215
+ ],
216
+ "license": "MIT",
217
+ "bin": {
218
+ "nanoid": "bin/nanoid.cjs"
219
+ },
220
+ "engines": {
221
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
222
+ }
223
+ },
224
+ "node_modules/picocolors": {
225
+ "version": "1.1.1",
226
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
227
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
228
+ "license": "ISC"
229
+ },
230
+ "node_modules/postcss": {
231
+ "version": "8.4.47",
232
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz",
233
+ "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==",
234
+ "funding": [
235
+ {
236
+ "type": "opencollective",
237
+ "url": "https://opencollective.com/postcss/"
238
+ },
239
+ {
240
+ "type": "tidelift",
241
+ "url": "https://tidelift.com/funding/github/npm/postcss"
242
+ },
243
+ {
244
+ "type": "github",
245
+ "url": "https://github.com/sponsors/ai"
246
+ }
247
+ ],
248
+ "license": "MIT",
249
+ "dependencies": {
250
+ "nanoid": "^3.3.7",
251
+ "picocolors": "^1.1.0",
252
+ "source-map-js": "^1.2.1"
253
+ },
254
+ "engines": {
255
+ "node": "^10 || ^12 || >=14"
256
+ }
257
+ },
258
+ "node_modules/source-map-js": {
259
+ "version": "1.2.1",
260
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
261
+ "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
262
+ "license": "BSD-3-Clause",
263
+ "engines": {
264
+ "node": ">=0.10.0"
265
+ }
266
+ },
267
+ "node_modules/vue": {
268
+ "version": "3.5.12",
269
+ "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.12.tgz",
270
+ "integrity": "sha512-CLVZtXtn2ItBIi/zHZ0Sg1Xkb7+PU32bJJ8Bmy7ts3jxXTcbfsEfBivFYYWz1Hur+lalqGAh65Coin0r+HRUfg==",
271
+ "license": "MIT",
272
+ "dependencies": {
273
+ "@vue/compiler-dom": "3.5.12",
274
+ "@vue/compiler-sfc": "3.5.12",
275
+ "@vue/runtime-dom": "3.5.12",
276
+ "@vue/server-renderer": "3.5.12",
277
+ "@vue/shared": "3.5.12"
278
+ },
279
+ "peerDependencies": {
280
+ "typescript": "*"
281
+ },
282
+ "peerDependenciesMeta": {
283
+ "typescript": {
284
+ "optional": true
285
+ }
286
+ }
287
+ },
288
+ "node_modules/vue3-otp-input": {
289
+ "version": "0.5.21",
290
+ "resolved": "https://registry.npmjs.org/vue3-otp-input/-/vue3-otp-input-0.5.21.tgz",
291
+ "integrity": "sha512-dRxmGJqXlU+U5dCijNCyY7ird49+pyfeQspSTqvIp2Xs+VByIluNlTOjgHrftzSdeVZggtx+Ojb8uKiRLaob4Q==",
292
+ "license": "MIT",
293
+ "dependencies": {
294
+ "vue": "^3.4.27"
295
+ },
296
+ "peerDependencies": {
297
+ "vue": "^3.0.*"
298
+ }
19
299
  }
20
300
  }
21
301
  }
@@ -10,6 +10,7 @@
10
10
  "license": "ISC",
11
11
  "description": "",
12
12
  "dependencies": {
13
- "@loltech/vue3-2fa-code-input": "^1.1.0"
13
+ "@loltech/vue3-2fa-code-input": "^1.1.0",
14
+ "vue3-otp-input": "^0.5.21"
14
15
  }
15
16
  }
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <div class="relative flex items-center justify-center min-h-screen bg-gray-100 dark:bg-gray-800"
3
- :style="coreStore.config?.loginBackgroundImage ? {
3
+ :style="(coreStore.config?.loginBackgroundImage && coreStore.config?.loginBackgroundPosition === 'over') ? {
4
4
  'background-image': 'url(' + loadFile(coreStore.config?.loginBackgroundImage) + ')',
5
5
  'background-size': 'cover',
6
6
  'background-position': 'center',
@@ -14,7 +14,21 @@
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
16
  <div class="m-3" >Please enter your authenticator code </div>
17
- <Vue2FACodeInput v-model="code"/>
17
+ <div class="my-4 flex justify-center items-center">
18
+ <v-otp-input
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"
21
+ :conditionalClass="['one', 'two', 'three', 'four', 'five', 'six']"
22
+ inputType="number"
23
+ :num-inputs="6"
24
+ v-model:value="bindValue"
25
+ :should-auto-focus="true"
26
+ :should-focus-order="true"
27
+ @on-change="handleOnChange"
28
+ @on-complete="handleOnComplete"
29
+ />
30
+ </div>
31
+ <!-- <Vue2FACodeInput v-model="code"/> -->
18
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">
19
33
  Cancel
20
34
  </button>
@@ -31,17 +45,26 @@
31
45
 
32
46
  <script setup>
33
47
 
34
- import { onMounted, ref, watchEffect,computed,watch } from 'vue';
48
+ import { onMounted, onBeforeUnmount, ref, watchEffect,computed,watch } from 'vue';
35
49
  import { useCoreStore } from '@/stores/core';
36
50
  import { useUserStore } from '@/stores/user';
37
51
  import { IconEyeSolid, IconEyeSlashSolid } from '@iconify-prerendered/vue-flowbite';
38
52
  import { callAdminForthApi, loadFile } from '@/utils';
39
53
  import { useRouter } from 'vue-router';
40
- import { initFlowbite } from 'flowbite'
41
54
  import { showErrorTost } from '@/composables/useFrontendApi';
42
55
  import Vue2FACodeInput from '@loltech/vue3-2fa-code-input';
56
+ import VOtpInput from "vue3-otp-input";
43
57
 
44
58
  const code = ref(null);
59
+
60
+ const handleOnComplete = (value) => {
61
+ sendCode(value);
62
+ };
63
+
64
+ const fillInput = (value) => {
65
+ code.value?.fillInput(value);
66
+ };
67
+
45
68
  const router = useRouter();
46
69
  const inProgress = ref(false);
47
70
 
@@ -75,16 +98,22 @@
75
98
  }
76
99
 
77
100
  onMounted(async () => {
78
- coreStore.getPublicConfig()
101
+ coreStore.getPublicConfig();
102
+ window.addEventListener('keydown', handleKeydown);
79
103
  });
104
+
105
+ onBeforeUnmount(() => {
106
+ window.removeEventListener('keydown', handleKeydown);
107
+ });
108
+
80
109
 
81
- async function sendCode () {
110
+ async function sendCode (value) {
82
111
  inProgress.value = true;
83
112
  const resp = await callAdminForthApi({
84
113
  method: 'POST',
85
114
  path: '/plugin/twofa/confirmSetup',
86
115
  body: {
87
- code: code.value,
116
+ code: value,
88
117
  secret: null,
89
118
  }
90
119
  })
@@ -95,11 +124,24 @@
95
124
  }
96
125
  }
97
126
 
98
- watch(code, async (nv)=>{
99
- if (nv){
100
- sendCode();
127
+ // watch(code, async (nv)=>{
128
+ // if (nv){
129
+ // sendCode();
130
+ // }
131
+ // })
132
+
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
+ });
101
143
  }
102
- })
144
+ }
103
145
  </script>
104
146
 
105
147
  <style lang='scss'>
@@ -109,7 +151,9 @@
109
151
  gap: 1rem;
110
152
  margin-bottom: 1rem;
111
153
  }
112
-
154
+ .otp-input {
155
+ margin: 0 5px;
156
+ }
113
157
  .vue3-2fa-code-input-box {
114
158
  &[type='text'] {
115
159
  @apply w-10 h-10 text-center text-xl border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500;
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <div class="relative flex items-center justify-center min-h-screen bg-gray-100 dark:bg-gray-800"
3
- :style="coreStore.config?.loginBackgroundImage ? {
3
+ :style="coreStore.config?.loginBackgroundImage && coreStore.config?.loginBackgroundPosition === 'over' ? {
4
4
  'background-image': 'url(' + loadFile(coreStore.config?.loginBackgroundImage) + ')',
5
5
  'background-size': 'cover',
6
6
  'background-position': 'center',
@@ -40,7 +40,20 @@
40
40
  </div>
41
41
  </div>
42
42
  </div>
43
- <Vue2FACodeInput v-model="code"/>
43
+ <div class="my-4 flex justify-center items-center">
44
+ <v-otp-input
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"
47
+ :conditionalClass="['one', 'two', 'three', 'four', 'five', 'six']"
48
+ inputType="number"
49
+ :num-inputs="6"
50
+ :should-auto-focus="true"
51
+ :should-focus-order="true"
52
+ @on-complete="handleOnComplete"
53
+ />
54
+ </div>
55
+
56
+ <!-- <Vue2FACodeInput v-model="code" autofocus /> -->
44
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>
45
58
  </div>
46
59
  </div>
@@ -55,7 +68,7 @@
55
68
 
56
69
  <script setup>
57
70
 
58
- import { onMounted, ref, watchEffect,computed,watch } from 'vue';
71
+ import { onMounted, onBeforeUnmount, ref, watchEffect,computed,watch } from 'vue';
59
72
  import { useCoreStore } from '@/stores/core';
60
73
  import { useUserStore } from '@/stores/user';
61
74
  import { IconEyeSolid, IconEyeSlashSolid } from '@iconify-prerendered/vue-flowbite';
@@ -63,8 +76,16 @@ import { callAdminForthApi, loadFile } from '@/utils';
63
76
  import { useRouter } from 'vue-router';
64
77
  import { showErrorTost } from '@/composables/useFrontendApi';
65
78
  import Vue2FACodeInput from '@loltech/vue3-2fa-code-input';
79
+ import VOtpInput from "vue3-otp-input";
66
80
 
67
81
  const code = ref(null);
82
+ const handleOnComplete = (value) => {
83
+ sendCode(value);
84
+ };
85
+
86
+ const fillInput = (value) => {
87
+ code.value?.fillInput(value);
88
+ };
68
89
 
69
90
  const router = useRouter();
70
91
  const inProgress = ref(false);
@@ -76,6 +97,7 @@ const user = useUserStore();
76
97
 
77
98
 
78
99
 
100
+
79
101
  const showPw = ref(false);
80
102
 
81
103
  const error = ref(null);
@@ -108,11 +130,12 @@ function onCopyClick(){
108
130
  window.adminforth.alert({message: 'Copied to clipboard', variant: 'success'})
109
131
  }
110
132
 
111
- watch(code, async (nv)=>{
112
- if (nv){
113
- sendCode();
114
- }
115
- })
133
+ // watch(code, async (nv)=>{
134
+ // if (nv){
135
+ // console.log(code.value);
136
+ // sendCode();
137
+ // }
138
+ // })
116
139
 
117
140
  onMounted(async () => {
118
141
  coreStore.getPublicConfig()
@@ -126,16 +149,22 @@ onMounted(async () => {
126
149
 
127
150
  totp.value=parseJwt(totpJWT.value);
128
151
 
152
+ window.addEventListener('keydown', handleKeydown);
153
+ });
129
154
 
155
+ onBeforeUnmount(() => {
156
+ window.removeEventListener('keydown', handleKeydown);
130
157
  });
131
158
 
132
- async function sendCode () {
159
+ async function sendCode (value) {
133
160
  inProgress.value = true;
161
+
162
+
134
163
  const resp = await callAdminForthApi({
135
164
  method: 'POST',
136
165
  path: '/plugin/twofa/confirmSetup',
137
166
  body: {
138
- code: code.value,
167
+ code: value,
139
168
  secret: totp.value.newSecret,
140
169
  }
141
170
  })
@@ -145,4 +174,24 @@ async function sendCode () {
145
174
  showErrorTost('Invalid code');
146
175
  }
147
176
  }
177
+
178
+
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
+ });
189
+ }
190
+ }
148
191
  </script>
192
+ <style>
193
+ .otp-input {
194
+ margin: 0 5px;
195
+
196
+ }
197
+ </style>
@@ -9,13 +9,293 @@
9
9
  "version": "1.0.0",
10
10
  "license": "ISC",
11
11
  "dependencies": {
12
- "@loltech/vue3-2fa-code-input": "^1.1.0"
12
+ "@loltech/vue3-2fa-code-input": "^1.1.0",
13
+ "vue3-otp-input": "^0.5.21"
13
14
  }
14
15
  },
16
+ "node_modules/@babel/helper-string-parser": {
17
+ "version": "7.25.9",
18
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz",
19
+ "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==",
20
+ "license": "MIT",
21
+ "engines": {
22
+ "node": ">=6.9.0"
23
+ }
24
+ },
25
+ "node_modules/@babel/helper-validator-identifier": {
26
+ "version": "7.25.9",
27
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz",
28
+ "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==",
29
+ "license": "MIT",
30
+ "engines": {
31
+ "node": ">=6.9.0"
32
+ }
33
+ },
34
+ "node_modules/@babel/parser": {
35
+ "version": "7.25.9",
36
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.9.tgz",
37
+ "integrity": "sha512-aI3jjAAO1fh7vY/pBGsn1i9LDbRP43+asrRlkPuTXW5yHXtd1NgTEMudbBoDDxrf1daEEfPJqR+JBMakzrR4Dg==",
38
+ "license": "MIT",
39
+ "dependencies": {
40
+ "@babel/types": "^7.25.9"
41
+ },
42
+ "bin": {
43
+ "parser": "bin/babel-parser.js"
44
+ },
45
+ "engines": {
46
+ "node": ">=6.0.0"
47
+ }
48
+ },
49
+ "node_modules/@babel/types": {
50
+ "version": "7.25.9",
51
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.9.tgz",
52
+ "integrity": "sha512-OwS2CM5KocvQ/k7dFJa8i5bNGJP0hXWfVCfDkqRFP1IreH1JDC7wG6eCYCi0+McbfT8OR/kNqsI0UU0xP9H6PQ==",
53
+ "license": "MIT",
54
+ "dependencies": {
55
+ "@babel/helper-string-parser": "^7.25.9",
56
+ "@babel/helper-validator-identifier": "^7.25.9"
57
+ },
58
+ "engines": {
59
+ "node": ">=6.9.0"
60
+ }
61
+ },
62
+ "node_modules/@jridgewell/sourcemap-codec": {
63
+ "version": "1.5.0",
64
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
65
+ "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==",
66
+ "license": "MIT"
67
+ },
15
68
  "node_modules/@loltech/vue3-2fa-code-input": {
16
69
  "version": "1.1.0",
17
70
  "resolved": "https://registry.npmjs.org/@loltech/vue3-2fa-code-input/-/vue3-2fa-code-input-1.1.0.tgz",
18
71
  "integrity": "sha512-styyoQjsARSeVf6E5qMvYIVkLRrwYtfL8xDl5W+g9wKF8qlr2XGU2gi9maEg0X4Us41kJryXBzfRMUcv5tKIBA=="
72
+ },
73
+ "node_modules/@vue/compiler-core": {
74
+ "version": "3.5.12",
75
+ "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.12.tgz",
76
+ "integrity": "sha512-ISyBTRMmMYagUxhcpyEH0hpXRd/KqDU4ymofPgl2XAkY9ZhQ+h0ovEZJIiPop13UmR/54oA2cgMDjgroRelaEw==",
77
+ "license": "MIT",
78
+ "dependencies": {
79
+ "@babel/parser": "^7.25.3",
80
+ "@vue/shared": "3.5.12",
81
+ "entities": "^4.5.0",
82
+ "estree-walker": "^2.0.2",
83
+ "source-map-js": "^1.2.0"
84
+ }
85
+ },
86
+ "node_modules/@vue/compiler-dom": {
87
+ "version": "3.5.12",
88
+ "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.12.tgz",
89
+ "integrity": "sha512-9G6PbJ03uwxLHKQ3P42cMTi85lDRvGLB2rSGOiQqtXELat6uI4n8cNz9yjfVHRPIu+MsK6TE418Giruvgptckg==",
90
+ "license": "MIT",
91
+ "dependencies": {
92
+ "@vue/compiler-core": "3.5.12",
93
+ "@vue/shared": "3.5.12"
94
+ }
95
+ },
96
+ "node_modules/@vue/compiler-sfc": {
97
+ "version": "3.5.12",
98
+ "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.12.tgz",
99
+ "integrity": "sha512-2k973OGo2JuAa5+ZlekuQJtitI5CgLMOwgl94BzMCsKZCX/xiqzJYzapl4opFogKHqwJk34vfsaKpfEhd1k5nw==",
100
+ "license": "MIT",
101
+ "dependencies": {
102
+ "@babel/parser": "^7.25.3",
103
+ "@vue/compiler-core": "3.5.12",
104
+ "@vue/compiler-dom": "3.5.12",
105
+ "@vue/compiler-ssr": "3.5.12",
106
+ "@vue/shared": "3.5.12",
107
+ "estree-walker": "^2.0.2",
108
+ "magic-string": "^0.30.11",
109
+ "postcss": "^8.4.47",
110
+ "source-map-js": "^1.2.0"
111
+ }
112
+ },
113
+ "node_modules/@vue/compiler-ssr": {
114
+ "version": "3.5.12",
115
+ "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.12.tgz",
116
+ "integrity": "sha512-eLwc7v6bfGBSM7wZOGPmRavSWzNFF6+PdRhE+VFJhNCgHiF8AM7ccoqcv5kBXA2eWUfigD7byekvf/JsOfKvPA==",
117
+ "license": "MIT",
118
+ "dependencies": {
119
+ "@vue/compiler-dom": "3.5.12",
120
+ "@vue/shared": "3.5.12"
121
+ }
122
+ },
123
+ "node_modules/@vue/reactivity": {
124
+ "version": "3.5.12",
125
+ "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.12.tgz",
126
+ "integrity": "sha512-UzaN3Da7xnJXdz4Okb/BGbAaomRHc3RdoWqTzlvd9+WBR5m3J39J1fGcHes7U3za0ruYn/iYy/a1euhMEHvTAg==",
127
+ "license": "MIT",
128
+ "dependencies": {
129
+ "@vue/shared": "3.5.12"
130
+ }
131
+ },
132
+ "node_modules/@vue/runtime-core": {
133
+ "version": "3.5.12",
134
+ "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.12.tgz",
135
+ "integrity": "sha512-hrMUYV6tpocr3TL3Ad8DqxOdpDe4zuQY4HPY3X/VRh+L2myQO8MFXPAMarIOSGNu0bFAjh1yBkMPXZBqCk62Uw==",
136
+ "license": "MIT",
137
+ "dependencies": {
138
+ "@vue/reactivity": "3.5.12",
139
+ "@vue/shared": "3.5.12"
140
+ }
141
+ },
142
+ "node_modules/@vue/runtime-dom": {
143
+ "version": "3.5.12",
144
+ "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.12.tgz",
145
+ "integrity": "sha512-q8VFxR9A2MRfBr6/55Q3umyoN7ya836FzRXajPB6/Vvuv0zOPL+qltd9rIMzG/DbRLAIlREmnLsplEF/kotXKA==",
146
+ "license": "MIT",
147
+ "dependencies": {
148
+ "@vue/reactivity": "3.5.12",
149
+ "@vue/runtime-core": "3.5.12",
150
+ "@vue/shared": "3.5.12",
151
+ "csstype": "^3.1.3"
152
+ }
153
+ },
154
+ "node_modules/@vue/server-renderer": {
155
+ "version": "3.5.12",
156
+ "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.12.tgz",
157
+ "integrity": "sha512-I3QoeDDeEPZm8yR28JtY+rk880Oqmj43hreIBVTicisFTx/Dl7JpG72g/X7YF8hnQD3IFhkky5i2bPonwrTVPg==",
158
+ "license": "MIT",
159
+ "dependencies": {
160
+ "@vue/compiler-ssr": "3.5.12",
161
+ "@vue/shared": "3.5.12"
162
+ },
163
+ "peerDependencies": {
164
+ "vue": "3.5.12"
165
+ }
166
+ },
167
+ "node_modules/@vue/shared": {
168
+ "version": "3.5.12",
169
+ "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.12.tgz",
170
+ "integrity": "sha512-L2RPSAwUFbgZH20etwrXyVyCBu9OxRSi8T/38QsvnkJyvq2LufW2lDCOzm7t/U9C1mkhJGWYfCuFBCmIuNivrg==",
171
+ "license": "MIT"
172
+ },
173
+ "node_modules/csstype": {
174
+ "version": "3.1.3",
175
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
176
+ "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
177
+ "license": "MIT"
178
+ },
179
+ "node_modules/entities": {
180
+ "version": "4.5.0",
181
+ "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
182
+ "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
183
+ "license": "BSD-2-Clause",
184
+ "engines": {
185
+ "node": ">=0.12"
186
+ },
187
+ "funding": {
188
+ "url": "https://github.com/fb55/entities?sponsor=1"
189
+ }
190
+ },
191
+ "node_modules/estree-walker": {
192
+ "version": "2.0.2",
193
+ "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
194
+ "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
195
+ "license": "MIT"
196
+ },
197
+ "node_modules/magic-string": {
198
+ "version": "0.30.12",
199
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.12.tgz",
200
+ "integrity": "sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw==",
201
+ "license": "MIT",
202
+ "dependencies": {
203
+ "@jridgewell/sourcemap-codec": "^1.5.0"
204
+ }
205
+ },
206
+ "node_modules/nanoid": {
207
+ "version": "3.3.7",
208
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
209
+ "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
210
+ "funding": [
211
+ {
212
+ "type": "github",
213
+ "url": "https://github.com/sponsors/ai"
214
+ }
215
+ ],
216
+ "license": "MIT",
217
+ "bin": {
218
+ "nanoid": "bin/nanoid.cjs"
219
+ },
220
+ "engines": {
221
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
222
+ }
223
+ },
224
+ "node_modules/picocolors": {
225
+ "version": "1.1.1",
226
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
227
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
228
+ "license": "ISC"
229
+ },
230
+ "node_modules/postcss": {
231
+ "version": "8.4.47",
232
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz",
233
+ "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==",
234
+ "funding": [
235
+ {
236
+ "type": "opencollective",
237
+ "url": "https://opencollective.com/postcss/"
238
+ },
239
+ {
240
+ "type": "tidelift",
241
+ "url": "https://tidelift.com/funding/github/npm/postcss"
242
+ },
243
+ {
244
+ "type": "github",
245
+ "url": "https://github.com/sponsors/ai"
246
+ }
247
+ ],
248
+ "license": "MIT",
249
+ "dependencies": {
250
+ "nanoid": "^3.3.7",
251
+ "picocolors": "^1.1.0",
252
+ "source-map-js": "^1.2.1"
253
+ },
254
+ "engines": {
255
+ "node": "^10 || ^12 || >=14"
256
+ }
257
+ },
258
+ "node_modules/source-map-js": {
259
+ "version": "1.2.1",
260
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
261
+ "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
262
+ "license": "BSD-3-Clause",
263
+ "engines": {
264
+ "node": ">=0.10.0"
265
+ }
266
+ },
267
+ "node_modules/vue": {
268
+ "version": "3.5.12",
269
+ "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.12.tgz",
270
+ "integrity": "sha512-CLVZtXtn2ItBIi/zHZ0Sg1Xkb7+PU32bJJ8Bmy7ts3jxXTcbfsEfBivFYYWz1Hur+lalqGAh65Coin0r+HRUfg==",
271
+ "license": "MIT",
272
+ "dependencies": {
273
+ "@vue/compiler-dom": "3.5.12",
274
+ "@vue/compiler-sfc": "3.5.12",
275
+ "@vue/runtime-dom": "3.5.12",
276
+ "@vue/server-renderer": "3.5.12",
277
+ "@vue/shared": "3.5.12"
278
+ },
279
+ "peerDependencies": {
280
+ "typescript": "*"
281
+ },
282
+ "peerDependenciesMeta": {
283
+ "typescript": {
284
+ "optional": true
285
+ }
286
+ }
287
+ },
288
+ "node_modules/vue3-otp-input": {
289
+ "version": "0.5.21",
290
+ "resolved": "https://registry.npmjs.org/vue3-otp-input/-/vue3-otp-input-0.5.21.tgz",
291
+ "integrity": "sha512-dRxmGJqXlU+U5dCijNCyY7ird49+pyfeQspSTqvIp2Xs+VByIluNlTOjgHrftzSdeVZggtx+Ojb8uKiRLaob4Q==",
292
+ "license": "MIT",
293
+ "dependencies": {
294
+ "vue": "^3.4.27"
295
+ },
296
+ "peerDependencies": {
297
+ "vue": "^3.0.*"
298
+ }
19
299
  }
20
300
  }
21
301
  }
@@ -10,6 +10,7 @@
10
10
  "license": "ISC",
11
11
  "description": "",
12
12
  "dependencies": {
13
- "@loltech/vue3-2fa-code-input": "^1.1.0"
13
+ "@loltech/vue3-2fa-code-input": "^1.1.0",
14
+ "vue3-otp-input": "^0.5.21"
14
15
  }
15
16
  }
package/dist/index.js CHANGED
@@ -60,7 +60,7 @@ export default class TwoFactorsAuthPlugin extends AdminForthPlugin {
60
60
  newSecret = tempSecret.secret;
61
61
  }
62
62
  else {
63
- const value = this.adminforth.auth.issueJWT({ userName, issuer: brandName, pk: userPk }, 'tempTotp');
63
+ const value = this.adminforth.auth.issueJWT({ userName, issuer: brandName, pk: userPk }, 'tempTotp', '2h');
64
64
  response.setHeader('Set-Cookie', `adminforth_totpTemporaryJWT=${value}; Path=${this.adminforth.config.baseUrl || '/'}; HttpOnly; SameSite=Strict; max-age=3600; `);
65
65
  return {
66
66
  body: {
@@ -70,7 +70,7 @@ export default class TwoFactorsAuthPlugin extends AdminForthPlugin {
70
70
  ok: true
71
71
  };
72
72
  }
73
- const totpTemporaryJWT = this.adminforth.auth.issueJWT({ userName, newSecret, issuer: brandName, pk: userPk }, 'tempTotp');
73
+ const totpTemporaryJWT = this.adminforth.auth.issueJWT({ userName, newSecret, issuer: brandName, pk: userPk }, 'tempTotp', '2h');
74
74
  response.setHeader('Set-Cookie', `adminforth_totpTemporaryJWT=${totpTemporaryJWT}; Path=${this.adminforth.config.baseUrl || '/'}; HttpOnly; SameSite=Strict; Expires=${new Date(Date.now() + '1h').toUTCString()} `);
75
75
  return {
76
76
  body: {
package/index.ts CHANGED
@@ -65,7 +65,7 @@ export default class TwoFactorsAuthPlugin extends AdminForthPlugin {
65
65
  const tempSecret = twofactor.generateSecret({name: brandName,account: userName})
66
66
  newSecret = tempSecret.secret
67
67
  } else {
68
- const value = this.adminforth.auth.issueJWT({userName, issuer:brandName, pk:userPk },'tempTotp');
68
+ const value = this.adminforth.auth.issueJWT({userName, issuer:brandName, pk:userPk }, 'tempTotp', '2h');
69
69
  response.setHeader('Set-Cookie', `adminforth_totpTemporaryJWT=${value}; Path=${this.adminforth.config.baseUrl || '/'}; HttpOnly; SameSite=Strict; max-age=3600; `);
70
70
 
71
71
  return {
@@ -76,7 +76,7 @@ export default class TwoFactorsAuthPlugin extends AdminForthPlugin {
76
76
  ok: true
77
77
  }
78
78
  }
79
- const totpTemporaryJWT = this.adminforth.auth.issueJWT({userName, newSecret, issuer:brandName, pk:userPk },'tempTotp', )
79
+ const totpTemporaryJWT = this.adminforth.auth.issueJWT({userName, newSecret, issuer:brandName, pk:userPk },'tempTotp', '2h');
80
80
  response.setHeader('Set-Cookie', `adminforth_totpTemporaryJWT=${totpTemporaryJWT}; Path=${this.adminforth.config.baseUrl || '/'}; HttpOnly; SameSite=Strict; Expires=${new Date(Date.now() + '1h').toUTCString() } `);
81
81
 
82
82
  return {
@@ -139,7 +139,7 @@ export default class TwoFactorsAuthPlugin extends AdminForthPlugin {
139
139
  } else {
140
140
  return {error: 'Wrong or expired OTP code'}
141
141
  }
142
- }
142
+ }
143
143
  }
144
144
  })
145
145
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adminforth/two-factors-auth",
3
- "version": "1.0.17",
3
+ "version": "1.0.19",
4
4
  "description": "AdminForth plugin for two factors authentication",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",