@adminforth/open-signup 1.0.2 → 1.0.4

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.
@@ -37,26 +37,28 @@
37
37
  <!-- Modal body -->
38
38
  <div class="p-4 md:p-5">
39
39
  <form v-if="!requestSent" class="space-y-4" role="alert" @submit.prevent>
40
- <div class="relative">
40
+ <div v-if="!verifyToken" class="relative">
41
41
  <label for="email" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Your email</label>
42
42
  <input type="email" name="email" id="email"
43
43
  tabindex="1"
44
- @keydown.enter="passwordInput.focus()"
44
+ autocomplete="username"
45
+ @keydown.enter="passwordInput?.focus()"
45
46
  ref="emailInput"
46
47
  class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-600 dark:border-gray-500 dark:placeholder-gray-400 dark:text-white"
47
48
  placeholder="name@company.com"
48
49
  required
49
50
  />
50
51
  </div>
51
- <div class="relative">
52
+ <div v-if="isPasswordNeeded" class="relative">
52
53
  <label for="password" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">New password</label>
53
54
  <input
54
55
  tabindex="2"
56
+ autocomplete="new-password"
55
57
  ref="passwordInput"
56
58
  :type="unmasked ? 'text' : 'password'"
57
59
  name="password" id="password"
58
60
  v-model="password"
59
- @keydown.enter="passwordConfirmationInput.focus()"
61
+ @keydown.enter="passwordConfirmationInput?.focus()"
60
62
  class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-600 dark:border-gray-500 dark:placeholder-gray-400 dark:text-white"
61
63
  placeholder="New password" required
62
64
  />
@@ -71,10 +73,11 @@
71
73
  </button>
72
74
  </div>
73
75
 
74
- <div class="relative">
76
+ <div v-if="isPasswordNeeded" class="relative">
75
77
  <label for="password_confirmation" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Confirm new password</label>
76
78
  <input
77
79
  ref="passwordConfirmationInput"
80
+ autocomplete="new-password"
78
81
  :type="unmasked ? 'text' : 'password'"
79
82
  name="password_confirmation" id="password_confirmation"
80
83
  tabindex="3"
@@ -105,7 +108,7 @@
105
108
 
106
109
  <Button
107
110
  :disabled="inProgress || (validationRunning && validationError)"
108
- @click="doSignup"
111
+ @click="() => verifyToken ? signupAfterEmailConfirmation() : doSignup()"
109
112
  type="submit"
110
113
  class="w-full"
111
114
  :loader="inProgress"
@@ -115,9 +118,11 @@
115
118
  </form>
116
119
  <!-- END of set new paasord -->
117
120
  <div v-else class="flex items center justify-center p-4 mb-4 text-sm text-green-800 rounded-lg bg-green-50 dark:bg-green-800 dark:text-green-400" role="alert">
118
- If user with specified email exists in our db, then request was sent. Please check your email at {{ sentToEmail }} to reset your password.
119
- </div>
120
-
121
+ Please check your email at {{ sentToEmail }} to confirm your email address.
122
+ </div>
123
+ <p class="text-gray-500 dark:text-gray-400 font-sm text-right mt-3">
124
+ or <Link to="/login">{{ toLoginText }}</Link>
125
+ </p>
121
126
  </div>
122
127
  </div>
123
128
  </div>
@@ -128,7 +133,6 @@
128
133
 
129
134
 
130
135
  <script setup lang="ts">
131
-
132
136
  import { onMounted, ref, computed, Ref } from 'vue';
133
137
  import { useCoreStore } from '@/stores/core';
134
138
  import { useUserStore } from '@/stores/user';
@@ -136,27 +140,33 @@ import { callAdminForthApi, loadFile, applyRegexValidation } from '@/utils';
136
140
  import { useRoute, useRouter } from 'vue-router';
137
141
  import { IconEyeSolid, IconEyeSlashSolid } from '@iconify-prerendered/vue-flowbite';
138
142
  import Button from '@/afcl/Button.vue';
143
+ import Link from '@/afcl/Link.vue';
139
144
 
140
145
  const inProgress = ref(false);
141
146
 
142
147
  const coreStore = useCoreStore();
143
148
  const requestSent = ref(false);
144
149
 
145
- const emailInput = ref(null);
146
- const passwordInput = ref(null);
147
- const passwordConfirmationInput = ref(null);
150
+ const emailInput: Ref<HTMLInputElement | null> = ref(null);
151
+ const passwordInput: Ref<HTMLInputElement | null> = ref(null);
152
+ const passwordConfirmationInput: Ref<HTMLInputElement | null> = ref(null);
148
153
 
149
154
  const password = ref("");
150
155
  const passwordConfirmation = ref("");
151
156
  const unmasked = ref(false);
152
157
  const sentToEmail: Ref<string> = ref('');
153
158
 
159
+ const requestEmailConfirmation = computed(() => route.meta.requestEmailConfirmation);
160
+ const verifyToken = computed(() => route.query.token);
161
+ const toLoginText = computed(() => `${verifyToken.value ? 'Go' : 'Back'} to login`);
162
+ const isPasswordNeeded = computed(() => !requestEmailConfirmation.value || (requestEmailConfirmation.value && verifyToken.value));
163
+
154
164
  const user = useUserStore();
155
165
 
156
166
  const route = useRoute();
157
167
  const router = useRouter();
158
168
 
159
- function checkPassowrd() {
169
+ function checkPassword() {
160
170
 
161
171
  if (!password.value || !passwordConfirmation.value) {
162
172
  return 'Please enter both password and password confirmation';
@@ -187,39 +197,15 @@ const validationRunning = ref(false);
187
197
 
188
198
  const validationError = computed(() => {
189
199
  if (validationRunning.value) {
190
- return checkPassowrd();
200
+ return checkPassword();
191
201
  }
192
202
  return null;
193
203
  });
194
204
 
195
- const error: Ref<str | null> = ref(null);
205
+ const error: Ref<string | null> = ref(null);
196
206
 
197
207
  onMounted(async () => {
198
- if (route.query.token) {
199
- // call method completeVerifiedSignup to confirm { token }
200
- // if success, then redirect to login page
201
-
202
- const resp = await callAdminForthApi({
203
- path: `/plugin/${route.meta.pluginInstanceId}/complete-verified-signup`,
204
- method: 'POST',
205
- body: {
206
- token: route.query.token,
207
- }
208
- });
209
- if (resp.error) {
210
- window.adminforth.alert({
211
- message: `Error fetching data: ${error.message}`,
212
- variant: 'danger',
213
- });
214
- } else if (resp.redirectTo) {
215
- router.push(resp.redirectTo);
216
- } else {
217
- await user.finishLogin();
218
- }
219
- return;
220
-
221
- }
222
- emailInput.value.focus();
208
+ emailInput.value?.focus();
223
209
  });
224
210
 
225
211
 
@@ -242,7 +228,7 @@ async function doSignup() {
242
228
  error.value = 'Please enter your email';
243
229
  return;
244
230
  }
245
- if (checkPassowrd()) {
231
+ if (!requestEmailConfirmation.value && checkPassword()) {
246
232
  validationRunning.value = true;
247
233
  return;
248
234
  }
@@ -254,7 +240,7 @@ async function doSignup() {
254
240
  body: {
255
241
  email,
256
242
  url: window.location.origin + window.location.pathname,
257
- password: password.value,
243
+ ...(!requestEmailConfirmation.value ? {password: password.value} : {}),
258
244
  }
259
245
  });
260
246
  inProgress.value = false;
@@ -264,15 +250,37 @@ async function doSignup() {
264
250
  error.value = null;
265
251
  requestSent.value = true;
266
252
  sentToEmail.value = email;
267
- if (resp.redirectTo) {
253
+ if (resp.redirectTo && !requestEmailConfirmation.value) {
268
254
  router.push(resp.redirectTo);
269
- } else {
255
+ } else if (!requestEmailConfirmation.value) {
270
256
  error.value = null;
271
257
  await user.finishLogin();
272
258
  }
273
259
  }
274
260
  }
275
261
 
276
-
277
-
262
+ const signupAfterEmailConfirmation = async () => {
263
+ if (checkPassword()) {
264
+ validationRunning.value = true;
265
+ return;
266
+ }
267
+ const resp = await callAdminForthApi({
268
+ path: `/plugin/${route.meta.pluginInstanceId}/complete-verified-signup`,
269
+ method: 'POST',
270
+ body: {
271
+ token: verifyToken.value,
272
+ password: password.value,
273
+ }
274
+ });
275
+ if (resp.error) {
276
+ window.adminforth.alert({
277
+ message: `Error fetching data: ${resp.error}`,
278
+ variant: 'danger',
279
+ });
280
+ } else if (resp.redirectTo) {
281
+ router.push(resp.redirectTo);
282
+ } else {
283
+ await user.finishLogin();
284
+ }
285
+ }
278
286
  </script>
@@ -37,26 +37,28 @@
37
37
  <!-- Modal body -->
38
38
  <div class="p-4 md:p-5">
39
39
  <form v-if="!requestSent" class="space-y-4" role="alert" @submit.prevent>
40
- <div class="relative">
40
+ <div v-if="!verifyToken" class="relative">
41
41
  <label for="email" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Your email</label>
42
42
  <input type="email" name="email" id="email"
43
43
  tabindex="1"
44
- @keydown.enter="passwordInput.focus()"
44
+ autocomplete="username"
45
+ @keydown.enter="passwordInput?.focus()"
45
46
  ref="emailInput"
46
47
  class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-600 dark:border-gray-500 dark:placeholder-gray-400 dark:text-white"
47
48
  placeholder="name@company.com"
48
49
  required
49
50
  />
50
51
  </div>
51
- <div class="relative">
52
+ <div v-if="isPasswordNeeded" class="relative">
52
53
  <label for="password" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">New password</label>
53
54
  <input
54
55
  tabindex="2"
56
+ autocomplete="new-password"
55
57
  ref="passwordInput"
56
58
  :type="unmasked ? 'text' : 'password'"
57
59
  name="password" id="password"
58
60
  v-model="password"
59
- @keydown.enter="passwordConfirmationInput.focus()"
61
+ @keydown.enter="passwordConfirmationInput?.focus()"
60
62
  class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-600 dark:border-gray-500 dark:placeholder-gray-400 dark:text-white"
61
63
  placeholder="New password" required
62
64
  />
@@ -71,10 +73,11 @@
71
73
  </button>
72
74
  </div>
73
75
 
74
- <div class="relative">
76
+ <div v-if="isPasswordNeeded" class="relative">
75
77
  <label for="password_confirmation" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Confirm new password</label>
76
78
  <input
77
79
  ref="passwordConfirmationInput"
80
+ autocomplete="new-password"
78
81
  :type="unmasked ? 'text' : 'password'"
79
82
  name="password_confirmation" id="password_confirmation"
80
83
  tabindex="3"
@@ -105,7 +108,7 @@
105
108
 
106
109
  <Button
107
110
  :disabled="inProgress || (validationRunning && validationError)"
108
- @click="doSignup"
111
+ @click="() => verifyToken ? signupAfterEmailConfirmation() : doSignup()"
109
112
  type="submit"
110
113
  class="w-full"
111
114
  :loader="inProgress"
@@ -115,9 +118,11 @@
115
118
  </form>
116
119
  <!-- END of set new paasord -->
117
120
  <div v-else class="flex items center justify-center p-4 mb-4 text-sm text-green-800 rounded-lg bg-green-50 dark:bg-green-800 dark:text-green-400" role="alert">
118
- If user with specified email exists in our db, then request was sent. Please check your email at {{ sentToEmail }} to reset your password.
119
- </div>
120
-
121
+ Please check your email at {{ sentToEmail }} to confirm your email address.
122
+ </div>
123
+ <p class="text-gray-500 dark:text-gray-400 font-sm text-right mt-3">
124
+ or <Link to="/login">{{ toLoginText }}</Link>
125
+ </p>
121
126
  </div>
122
127
  </div>
123
128
  </div>
@@ -128,7 +133,6 @@
128
133
 
129
134
 
130
135
  <script setup lang="ts">
131
-
132
136
  import { onMounted, ref, computed, Ref } from 'vue';
133
137
  import { useCoreStore } from '@/stores/core';
134
138
  import { useUserStore } from '@/stores/user';
@@ -136,27 +140,33 @@ import { callAdminForthApi, loadFile, applyRegexValidation } from '@/utils';
136
140
  import { useRoute, useRouter } from 'vue-router';
137
141
  import { IconEyeSolid, IconEyeSlashSolid } from '@iconify-prerendered/vue-flowbite';
138
142
  import Button from '@/afcl/Button.vue';
143
+ import Link from '@/afcl/Link.vue';
139
144
 
140
145
  const inProgress = ref(false);
141
146
 
142
147
  const coreStore = useCoreStore();
143
148
  const requestSent = ref(false);
144
149
 
145
- const emailInput = ref(null);
146
- const passwordInput = ref(null);
147
- const passwordConfirmationInput = ref(null);
150
+ const emailInput: Ref<HTMLInputElement | null> = ref(null);
151
+ const passwordInput: Ref<HTMLInputElement | null> = ref(null);
152
+ const passwordConfirmationInput: Ref<HTMLInputElement | null> = ref(null);
148
153
 
149
154
  const password = ref("");
150
155
  const passwordConfirmation = ref("");
151
156
  const unmasked = ref(false);
152
157
  const sentToEmail: Ref<string> = ref('');
153
158
 
159
+ const requestEmailConfirmation = computed(() => route.meta.requestEmailConfirmation);
160
+ const verifyToken = computed(() => route.query.token);
161
+ const toLoginText = computed(() => `${verifyToken.value ? 'Go' : 'Back'} to login`);
162
+ const isPasswordNeeded = computed(() => !requestEmailConfirmation.value || (requestEmailConfirmation.value && verifyToken.value));
163
+
154
164
  const user = useUserStore();
155
165
 
156
166
  const route = useRoute();
157
167
  const router = useRouter();
158
168
 
159
- function checkPassowrd() {
169
+ function checkPassword() {
160
170
 
161
171
  if (!password.value || !passwordConfirmation.value) {
162
172
  return 'Please enter both password and password confirmation';
@@ -187,39 +197,15 @@ const validationRunning = ref(false);
187
197
 
188
198
  const validationError = computed(() => {
189
199
  if (validationRunning.value) {
190
- return checkPassowrd();
200
+ return checkPassword();
191
201
  }
192
202
  return null;
193
203
  });
194
204
 
195
- const error: Ref<str | null> = ref(null);
205
+ const error: Ref<string | null> = ref(null);
196
206
 
197
207
  onMounted(async () => {
198
- if (route.query.token) {
199
- // call method completeVerifiedSignup to confirm { token }
200
- // if success, then redirect to login page
201
-
202
- const resp = await callAdminForthApi({
203
- path: `/plugin/${route.meta.pluginInstanceId}/complete-verified-signup`,
204
- method: 'POST',
205
- body: {
206
- token: route.query.token,
207
- }
208
- });
209
- if (resp.error) {
210
- window.adminforth.alert({
211
- message: `Error fetching data: ${error.message}`,
212
- variant: 'danger',
213
- });
214
- } else if (resp.redirectTo) {
215
- router.push(resp.redirectTo);
216
- } else {
217
- await user.finishLogin();
218
- }
219
- return;
220
-
221
- }
222
- emailInput.value.focus();
208
+ emailInput.value?.focus();
223
209
  });
224
210
 
225
211
 
@@ -242,7 +228,7 @@ async function doSignup() {
242
228
  error.value = 'Please enter your email';
243
229
  return;
244
230
  }
245
- if (checkPassowrd()) {
231
+ if (!requestEmailConfirmation.value && checkPassword()) {
246
232
  validationRunning.value = true;
247
233
  return;
248
234
  }
@@ -254,7 +240,7 @@ async function doSignup() {
254
240
  body: {
255
241
  email,
256
242
  url: window.location.origin + window.location.pathname,
257
- password: password.value,
243
+ ...(!requestEmailConfirmation.value ? {password: password.value} : {}),
258
244
  }
259
245
  });
260
246
  inProgress.value = false;
@@ -264,15 +250,37 @@ async function doSignup() {
264
250
  error.value = null;
265
251
  requestSent.value = true;
266
252
  sentToEmail.value = email;
267
- if (resp.redirectTo) {
253
+ if (resp.redirectTo && !requestEmailConfirmation.value) {
268
254
  router.push(resp.redirectTo);
269
- } else {
255
+ } else if (!requestEmailConfirmation.value) {
270
256
  error.value = null;
271
257
  await user.finishLogin();
272
258
  }
273
259
  }
274
260
  }
275
261
 
276
-
277
-
262
+ const signupAfterEmailConfirmation = async () => {
263
+ if (checkPassword()) {
264
+ validationRunning.value = true;
265
+ return;
266
+ }
267
+ const resp = await callAdminForthApi({
268
+ path: `/plugin/${route.meta.pluginInstanceId}/complete-verified-signup`,
269
+ method: 'POST',
270
+ body: {
271
+ token: verifyToken.value,
272
+ password: password.value,
273
+ }
274
+ });
275
+ if (resp.error) {
276
+ window.adminforth.alert({
277
+ message: `Error fetching data: ${resp.error}`,
278
+ variant: 'danger',
279
+ });
280
+ } else if (resp.redirectTo) {
281
+ router.push(resp.redirectTo);
282
+ } else {
283
+ await user.finishLogin();
284
+ }
285
+ }
278
286
  </script>