nuxt-users 1.32.0 → 1.34.0
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 +44 -0
- package/dist/module.d.mts +1 -1
- package/dist/module.d.ts +1 -1
- package/dist/module.json +1 -1
- package/dist/module.mjs +1 -0
- package/dist/runtime/components/NUsersEmailConfirmation.vue +152 -0
- package/dist/runtime/components/NUsersEmailConfirmation.vue.d.ts +37 -0
- package/dist/runtime/components/NUsersLoginForm.vue.d.ts +2 -2
- package/dist/runtime/components/NUsersLogoutLink.vue.d.ts +2 -2
- package/dist/runtime/components/NUsersRegisterForm.vue.d.ts +4 -4
- package/dist/runtime/components/NUsersResetPasswordForm.vue.d.ts +2 -2
- package/dist/runtime/composables/usePasswordValidation.d.ts +1 -1
- package/dist/runtime/server/api/nuxt-users/confirm-email.get.d.ts +1 -4
- package/dist/runtime/server/api/nuxt-users/confirm-email.get.js +21 -21
- package/dist/runtime/server/services/registration.js +2 -1
- package/dist/shared/{nuxt-users.CFq7zOql.d.mts → nuxt-users.BOm7L39P.d.mts} +7 -0
- package/dist/shared/{nuxt-users.CFq7zOql.d.ts → nuxt-users.BOm7L39P.d.ts} +7 -0
- package/dist/utils.d.mts +1 -1
- package/dist/utils.d.ts +1 -1
- package/package.json +1 -1
- package/scripts/deploy-docs.sh +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,50 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
3
|
|
|
4
|
+
## v1.34.0
|
|
5
|
+
|
|
6
|
+
[compare changes](https://github.com/rrd108/nuxt-users/compare/v1.33.0...v1.34.0)
|
|
7
|
+
|
|
8
|
+
### 🚀 Enhancements
|
|
9
|
+
|
|
10
|
+
- Add email confirmation component ([9df6a76](https://github.com/rrd108/nuxt-users/commit/9df6a76))
|
|
11
|
+
|
|
12
|
+
### 🩹 Fixes
|
|
13
|
+
|
|
14
|
+
- Register date issue with MySQL ([28a5c00](https://github.com/rrd108/nuxt-users/commit/28a5c00))
|
|
15
|
+
|
|
16
|
+
### 🏡 Chore
|
|
17
|
+
|
|
18
|
+
- **release:** V1.33.0 ([df1b1a5](https://github.com/rrd108/nuxt-users/commit/df1b1a5))
|
|
19
|
+
|
|
20
|
+
### ❤️ Contributors
|
|
21
|
+
|
|
22
|
+
- Rrd108 ([@rrd108](https://github.com/rrd108))
|
|
23
|
+
|
|
24
|
+
## v1.33.0
|
|
25
|
+
|
|
26
|
+
[compare changes](https://github.com/rrd108/nuxt-users/compare/v1.32.0...v1.33.0)
|
|
27
|
+
|
|
28
|
+
### 🚀 Enhancements
|
|
29
|
+
|
|
30
|
+
- Extends NUsersList component with function filters ([be9a730](https://github.com/rrd108/nuxt-users/commit/be9a730))
|
|
31
|
+
|
|
32
|
+
### 🩹 Fixes
|
|
33
|
+
|
|
34
|
+
- Register date issue with MySQL ([28a5c00](https://github.com/rrd108/nuxt-users/commit/28a5c00))
|
|
35
|
+
|
|
36
|
+
### 💅 Refactors
|
|
37
|
+
|
|
38
|
+
- Remove unused code ([cbff5a0](https://github.com/rrd108/nuxt-users/commit/cbff5a0))
|
|
39
|
+
|
|
40
|
+
### 🏡 Chore
|
|
41
|
+
|
|
42
|
+
- **release:** V1.32.0 ([7021fb7](https://github.com/rrd108/nuxt-users/commit/7021fb7))
|
|
43
|
+
|
|
44
|
+
### ❤️ Contributors
|
|
45
|
+
|
|
46
|
+
- Rrd108 ([@rrd108](https://github.com/rrd108))
|
|
47
|
+
|
|
4
48
|
## v1.32.0
|
|
5
49
|
|
|
6
50
|
[compare changes](https://github.com/rrd108/nuxt-users/compare/v1.31.2...v1.32.0)
|
package/dist/module.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as _nuxt_schema from '@nuxt/schema';
|
|
2
|
-
import { R as RuntimeModuleOptions, M as ModuleOptions } from './shared/nuxt-users.
|
|
2
|
+
import { R as RuntimeModuleOptions, M as ModuleOptions } from './shared/nuxt-users.BOm7L39P.mjs';
|
|
3
3
|
export * from '../dist/runtime/server/internal/index.js';
|
|
4
4
|
|
|
5
5
|
declare const defaultOptions: ModuleOptions;
|
package/dist/module.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as _nuxt_schema from '@nuxt/schema';
|
|
2
|
-
import { R as RuntimeModuleOptions, M as ModuleOptions } from './shared/nuxt-users.
|
|
2
|
+
import { R as RuntimeModuleOptions, M as ModuleOptions } from './shared/nuxt-users.BOm7L39P.js';
|
|
3
3
|
export * from '../dist/runtime/server/internal/index.js';
|
|
4
4
|
|
|
5
5
|
declare const defaultOptions: ModuleOptions;
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import { computed } from "vue";
|
|
3
|
+
import { useRoute } from "#app";
|
|
4
|
+
const route = useRoute();
|
|
5
|
+
const status = computed(() => route.query.status);
|
|
6
|
+
const message = computed(() => route.query.message);
|
|
7
|
+
const isSuccess = computed(() => status.value === "success");
|
|
8
|
+
const isError = computed(() => status.value === "error");
|
|
9
|
+
const _props = defineProps({
|
|
10
|
+
successTitle: { type: String, required: false, default: "Email Confirmed!" },
|
|
11
|
+
errorTitle: { type: String, required: false, default: "Confirmation Failed" },
|
|
12
|
+
loginButtonText: { type: String, required: false, default: "Continue to Login" },
|
|
13
|
+
loginUrl: { type: String, required: false, default: "/login" },
|
|
14
|
+
showLoginButton: { type: Boolean, required: false, default: true }
|
|
15
|
+
});
|
|
16
|
+
</script>
|
|
17
|
+
|
|
18
|
+
<template>
|
|
19
|
+
<div class="n-users-section">
|
|
20
|
+
<div class="n-users-card">
|
|
21
|
+
<!-- Success state -->
|
|
22
|
+
<div
|
|
23
|
+
v-if="isSuccess"
|
|
24
|
+
class="n-users-confirmation-content"
|
|
25
|
+
>
|
|
26
|
+
<slot name="success-icon">
|
|
27
|
+
<div class="n-users-confirmation-icon n-users-confirmation-success">
|
|
28
|
+
<svg
|
|
29
|
+
viewBox="0 0 24 24"
|
|
30
|
+
fill="none"
|
|
31
|
+
stroke="currentColor"
|
|
32
|
+
stroke-width="2"
|
|
33
|
+
>
|
|
34
|
+
<path d="m9 12 2 2 4-4" />
|
|
35
|
+
<circle
|
|
36
|
+
cx="12"
|
|
37
|
+
cy="12"
|
|
38
|
+
r="10"
|
|
39
|
+
/>
|
|
40
|
+
</svg>
|
|
41
|
+
</div>
|
|
42
|
+
</slot>
|
|
43
|
+
|
|
44
|
+
<div class="n-users-section-header">
|
|
45
|
+
<slot name="success-content">
|
|
46
|
+
<h1 class="n-users-login-title">
|
|
47
|
+
{{ successTitle }}
|
|
48
|
+
</h1>
|
|
49
|
+
<div class="n-users-success-message">
|
|
50
|
+
{{ message || "Your email has been confirmed and your account is now active." }}
|
|
51
|
+
</div>
|
|
52
|
+
</slot>
|
|
53
|
+
</div>
|
|
54
|
+
|
|
55
|
+
<slot name="success-actions">
|
|
56
|
+
<div
|
|
57
|
+
v-if="showLoginButton"
|
|
58
|
+
class="n-users-form-actions"
|
|
59
|
+
>
|
|
60
|
+
<a
|
|
61
|
+
:href="loginUrl"
|
|
62
|
+
class="n-users-btn n-users-btn-primary"
|
|
63
|
+
>
|
|
64
|
+
{{ loginButtonText }}
|
|
65
|
+
</a>
|
|
66
|
+
</div>
|
|
67
|
+
</slot>
|
|
68
|
+
</div>
|
|
69
|
+
|
|
70
|
+
<!-- Error state -->
|
|
71
|
+
<div
|
|
72
|
+
v-else-if="isError"
|
|
73
|
+
class="n-users-confirmation-content"
|
|
74
|
+
>
|
|
75
|
+
<slot name="error-icon">
|
|
76
|
+
<div class="n-users-confirmation-icon n-users-confirmation-error">
|
|
77
|
+
<svg
|
|
78
|
+
viewBox="0 0 24 24"
|
|
79
|
+
fill="none"
|
|
80
|
+
stroke="currentColor"
|
|
81
|
+
stroke-width="2"
|
|
82
|
+
>
|
|
83
|
+
<circle
|
|
84
|
+
cx="12"
|
|
85
|
+
cy="12"
|
|
86
|
+
r="10"
|
|
87
|
+
/>
|
|
88
|
+
<line
|
|
89
|
+
x1="15"
|
|
90
|
+
y1="9"
|
|
91
|
+
x2="9"
|
|
92
|
+
y2="15"
|
|
93
|
+
/>
|
|
94
|
+
<line
|
|
95
|
+
x1="9"
|
|
96
|
+
y1="9"
|
|
97
|
+
x2="15"
|
|
98
|
+
y2="15"
|
|
99
|
+
/>
|
|
100
|
+
</svg>
|
|
101
|
+
</div>
|
|
102
|
+
</slot>
|
|
103
|
+
|
|
104
|
+
<div class="n-users-section-header">
|
|
105
|
+
<slot name="error-content">
|
|
106
|
+
<h1 class="n-users-login-title">
|
|
107
|
+
{{ errorTitle }}
|
|
108
|
+
</h1>
|
|
109
|
+
<div class="n-users-error-message">
|
|
110
|
+
{{ message || "The confirmation link is invalid or has expired. Please try registering again or contact support." }}
|
|
111
|
+
</div>
|
|
112
|
+
</slot>
|
|
113
|
+
</div>
|
|
114
|
+
|
|
115
|
+
<slot name="error-actions">
|
|
116
|
+
<div class="n-users-form-actions">
|
|
117
|
+
<a
|
|
118
|
+
:href="loginUrl"
|
|
119
|
+
class="n-users-btn n-users-btn-secondary"
|
|
120
|
+
>
|
|
121
|
+
Back to Login
|
|
122
|
+
</a>
|
|
123
|
+
</div>
|
|
124
|
+
</slot>
|
|
125
|
+
</div>
|
|
126
|
+
|
|
127
|
+
<!-- Loading/unknown state -->
|
|
128
|
+
<div
|
|
129
|
+
v-else
|
|
130
|
+
class="n-users-confirmation-content"
|
|
131
|
+
>
|
|
132
|
+
<slot name="loading-content">
|
|
133
|
+
<div class="n-users-confirmation-icon">
|
|
134
|
+
<div class="n-users-loading-spinner n-users-confirmation-spinner" />
|
|
135
|
+
</div>
|
|
136
|
+
<div class="n-users-section-header">
|
|
137
|
+
<h1 class="n-users-login-title">
|
|
138
|
+
Processing...
|
|
139
|
+
</h1>
|
|
140
|
+
<div class="n-users-form-help">
|
|
141
|
+
Please wait while we process your email confirmation.
|
|
142
|
+
</div>
|
|
143
|
+
</div>
|
|
144
|
+
</slot>
|
|
145
|
+
</div>
|
|
146
|
+
</div>
|
|
147
|
+
</div>
|
|
148
|
+
</template>
|
|
149
|
+
|
|
150
|
+
<style scoped>
|
|
151
|
+
.n-users-confirmation-content{padding:2rem;text-align:center}.n-users-confirmation-icon{align-items:center;border-radius:50%;display:flex;height:80px;justify-content:center;margin:0 auto 2rem;width:80px}.n-users-confirmation-icon svg{height:40px;width:40px}.n-users-confirmation-success{background-color:var(--nu-color-success-light);color:var(--nu-color-success)}.n-users-confirmation-error{background-color:var(--nu-color-error-light);color:var(--nu-color-error)}.n-users-confirmation-spinner{border-color:var(--nu-color-primary);border-top-color:transparent;border-width:4px;height:40px;width:40px}@media (max-width:640px){.n-users-confirmation-content{padding:1.5rem}.n-users-confirmation-icon{height:60px;margin-bottom:1.5rem;width:60px}.n-users-confirmation-icon svg{height:30px;width:30px}}
|
|
152
|
+
</style>
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
interface Props {
|
|
2
|
+
successTitle?: string;
|
|
3
|
+
errorTitle?: string;
|
|
4
|
+
loginButtonText?: string;
|
|
5
|
+
loginUrl?: string;
|
|
6
|
+
showLoginButton?: boolean;
|
|
7
|
+
}
|
|
8
|
+
declare var __VLS_1: {}, __VLS_3: {}, __VLS_5: {}, __VLS_7: {}, __VLS_9: {}, __VLS_11: {}, __VLS_13: {};
|
|
9
|
+
type __VLS_Slots = {} & {
|
|
10
|
+
'success-icon'?: (props: typeof __VLS_1) => any;
|
|
11
|
+
} & {
|
|
12
|
+
'success-content'?: (props: typeof __VLS_3) => any;
|
|
13
|
+
} & {
|
|
14
|
+
'success-actions'?: (props: typeof __VLS_5) => any;
|
|
15
|
+
} & {
|
|
16
|
+
'error-icon'?: (props: typeof __VLS_7) => any;
|
|
17
|
+
} & {
|
|
18
|
+
'error-content'?: (props: typeof __VLS_9) => any;
|
|
19
|
+
} & {
|
|
20
|
+
'error-actions'?: (props: typeof __VLS_11) => any;
|
|
21
|
+
} & {
|
|
22
|
+
'loading-content'?: (props: typeof __VLS_13) => any;
|
|
23
|
+
};
|
|
24
|
+
declare const __VLS_component: import("vue").DefineComponent<Props, void, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<Props> & Readonly<{}>, {
|
|
25
|
+
successTitle: string;
|
|
26
|
+
errorTitle: string;
|
|
27
|
+
loginButtonText: string;
|
|
28
|
+
loginUrl: string;
|
|
29
|
+
showLoginButton: boolean;
|
|
30
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
31
|
+
declare const _default: __VLS_WithSlots<typeof __VLS_component, __VLS_Slots>;
|
|
32
|
+
export default _default;
|
|
33
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
34
|
+
new (): {
|
|
35
|
+
$slots: S;
|
|
36
|
+
};
|
|
37
|
+
};
|
|
@@ -26,15 +26,15 @@ type __VLS_Slots = {} & {
|
|
|
26
26
|
'error-message'?: (props: typeof __VLS_15) => any;
|
|
27
27
|
};
|
|
28
28
|
declare const __VLS_component: import("vue").DefineComponent<Props, void, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
29
|
+
success: (user: UserWithoutPassword) => any;
|
|
29
30
|
error: (error: string) => any;
|
|
30
31
|
submit: (data: LoginFormData) => any;
|
|
31
|
-
success: (user: UserWithoutPassword) => any;
|
|
32
32
|
"forgot-password-error": (error: string) => any;
|
|
33
33
|
"forgot-password-success": () => any;
|
|
34
34
|
}, string, import("vue").PublicProps, Readonly<Props> & Readonly<{
|
|
35
|
+
onSuccess?: ((user: UserWithoutPassword) => any) | undefined;
|
|
35
36
|
onError?: ((error: string) => any) | undefined;
|
|
36
37
|
onSubmit?: ((data: LoginFormData) => any) | undefined;
|
|
37
|
-
onSuccess?: ((user: UserWithoutPassword) => any) | undefined;
|
|
38
38
|
"onForgot-password-error"?: ((error: string) => any) | undefined;
|
|
39
39
|
"onForgot-password-success"?: (() => any) | undefined;
|
|
40
40
|
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
@@ -16,13 +16,13 @@ type __VLS_Slots = {} & {
|
|
|
16
16
|
default?: (props: typeof __VLS_1) => any;
|
|
17
17
|
};
|
|
18
18
|
declare const __VLS_component: import("vue").DefineComponent<LogoutLinkProps, void, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
19
|
+
success: () => any;
|
|
19
20
|
error: (error: string) => any;
|
|
20
21
|
click: () => any;
|
|
21
|
-
success: () => any;
|
|
22
22
|
}, string, import("vue").PublicProps, Readonly<LogoutLinkProps> & Readonly<{
|
|
23
|
+
onSuccess?: (() => any) | undefined;
|
|
23
24
|
onError?: ((error: string) => any) | undefined;
|
|
24
25
|
onClick?: (() => any) | undefined;
|
|
25
|
-
onSuccess?: (() => any) | undefined;
|
|
26
26
|
}>, {
|
|
27
27
|
redirectTo: string;
|
|
28
28
|
linkText: string;
|
|
@@ -37,19 +37,19 @@ type __VLS_Slots = {} & {
|
|
|
37
37
|
'error-message'?: (props: typeof __VLS_24) => any;
|
|
38
38
|
};
|
|
39
39
|
declare const __VLS_component: import("vue").DefineComponent<Props, void, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
40
|
-
error: (error: string) => any;
|
|
41
|
-
submit: (data: RegistrationFormData) => any;
|
|
42
40
|
success: (data: {
|
|
43
41
|
user: Omit<UserWithoutPassword, "active">;
|
|
44
42
|
message: string;
|
|
45
43
|
}) => any;
|
|
44
|
+
error: (error: string) => any;
|
|
45
|
+
submit: (data: RegistrationFormData) => any;
|
|
46
46
|
}, string, import("vue").PublicProps, Readonly<Props> & Readonly<{
|
|
47
|
-
onError?: ((error: string) => any) | undefined;
|
|
48
|
-
onSubmit?: ((data: RegistrationFormData) => any) | undefined;
|
|
49
47
|
onSuccess?: ((data: {
|
|
50
48
|
user: Omit<UserWithoutPassword, "active">;
|
|
51
49
|
message: string;
|
|
52
50
|
}) => any) | undefined;
|
|
51
|
+
onError?: ((error: string) => any) | undefined;
|
|
52
|
+
onSubmit?: ((data: RegistrationFormData) => any) | undefined;
|
|
53
53
|
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
54
54
|
declare const _default: __VLS_WithSlots<typeof __VLS_component, __VLS_Slots>;
|
|
55
55
|
export default _default;
|
|
@@ -4,13 +4,13 @@ interface Props {
|
|
|
4
4
|
redirectTo?: string;
|
|
5
5
|
}
|
|
6
6
|
declare const _default: import("vue").DefineComponent<Props, void, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
7
|
-
error: (error: string) => any;
|
|
8
7
|
success: (user: UserWithoutPassword) => any;
|
|
8
|
+
error: (error: string) => any;
|
|
9
9
|
"password-error": (error: string) => any;
|
|
10
10
|
"password-updated": () => any;
|
|
11
11
|
}, string, import("vue").PublicProps, Readonly<Props> & Readonly<{
|
|
12
|
-
onError?: ((error: string) => any) | undefined;
|
|
13
12
|
onSuccess?: ((user: UserWithoutPassword) => any) | undefined;
|
|
13
|
+
onError?: ((error: string) => any) | undefined;
|
|
14
14
|
"onPassword-error"?: ((error: string) => any) | undefined;
|
|
15
15
|
"onPassword-updated"?: (() => any) | undefined;
|
|
16
16
|
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
@@ -25,7 +25,7 @@ export declare const usePasswordValidation: (moduleOptions?: RuntimeModuleOption
|
|
|
25
25
|
isValid: import("vue").ComputedRef<boolean>;
|
|
26
26
|
errors: import("vue").ComputedRef<string[]>;
|
|
27
27
|
hints: import("vue").ComputedRef<string[]>;
|
|
28
|
-
strength: import("vue").ComputedRef<"
|
|
28
|
+
strength: import("vue").ComputedRef<"strong" | "weak" | "medium">;
|
|
29
29
|
score: import("vue").ComputedRef<number>;
|
|
30
30
|
strengthColor: import("vue").ComputedRef<string>;
|
|
31
31
|
strengthText: import("vue").ComputedRef<string>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { defineEventHandler, getQuery, sendRedirect } from "h3";
|
|
2
2
|
import { useRuntimeConfig } from "#imports";
|
|
3
3
|
import { confirmUserEmail } from "../../services/registration.js";
|
|
4
4
|
export default defineEventHandler(async (event) => {
|
|
@@ -7,36 +7,36 @@ export default defineEventHandler(async (event) => {
|
|
|
7
7
|
const options = nuxtUsers;
|
|
8
8
|
const query = getQuery(event);
|
|
9
9
|
if (!query.token || !query.email) {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
const redirectUrl = new URL(options.emailConfirmationUrl, "http://localhost");
|
|
11
|
+
redirectUrl.searchParams.set("status", "error");
|
|
12
|
+
redirectUrl.searchParams.set("message", "Token and email are required");
|
|
13
|
+
return sendRedirect(event, redirectUrl.pathname + redirectUrl.search, 302);
|
|
14
14
|
}
|
|
15
15
|
const token = String(query.token);
|
|
16
16
|
const email = String(query.email);
|
|
17
17
|
const success = await confirmUserEmail(token, email, options);
|
|
18
18
|
if (success) {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
const redirectUrl = new URL(options.emailConfirmationUrl, "http://localhost");
|
|
20
|
+
redirectUrl.searchParams.set("status", "success");
|
|
21
|
+
redirectUrl.searchParams.set("message", "Email confirmed successfully! Your account is now active. You can now log in.");
|
|
22
|
+
return sendRedirect(event, redirectUrl.pathname + redirectUrl.search, 302);
|
|
23
23
|
} else {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
24
|
+
const redirectUrl = new URL(options.emailConfirmationUrl, "http://localhost");
|
|
25
|
+
redirectUrl.searchParams.set("status", "error");
|
|
26
|
+
redirectUrl.searchParams.set("message", "Invalid or expired confirmation token");
|
|
27
|
+
return sendRedirect(event, redirectUrl.pathname + redirectUrl.search, 302);
|
|
28
28
|
}
|
|
29
29
|
} catch (error) {
|
|
30
30
|
console.error("[Nuxt Users] Email confirmation error:", error);
|
|
31
|
+
const { nuxtUsers } = useRuntimeConfig();
|
|
32
|
+
const options = nuxtUsers;
|
|
33
|
+
const redirectUrl = new URL(options.emailConfirmationUrl, "http://localhost");
|
|
34
|
+
redirectUrl.searchParams.set("status", "error");
|
|
31
35
|
if (error instanceof Error) {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
});
|
|
36
|
+
redirectUrl.searchParams.set("message", error.message);
|
|
37
|
+
} else {
|
|
38
|
+
redirectUrl.searchParams.set("message", "Email confirmation failed");
|
|
36
39
|
}
|
|
37
|
-
|
|
38
|
-
statusCode: 500,
|
|
39
|
-
statusMessage: "Email confirmation failed"
|
|
40
|
-
});
|
|
40
|
+
return sendRedirect(event, redirectUrl.pathname + redirectUrl.search, 302);
|
|
41
41
|
}
|
|
42
42
|
});
|
|
@@ -147,7 +147,8 @@ export const confirmUserEmail = async (token, email, options) => {
|
|
|
147
147
|
}
|
|
148
148
|
const now = /* @__PURE__ */ new Date();
|
|
149
149
|
const currentTimeString = now.toISOString().slice(0, 19).replace("T", " ");
|
|
150
|
-
const
|
|
150
|
+
const createdAtString = validTokenRecord.created_at instanceof Date ? validTokenRecord.created_at.toISOString().slice(0, 19).replace("T", " ") : String(validTokenRecord.created_at);
|
|
151
|
+
const [datePart, timePart] = createdAtString.split(/[ T]/);
|
|
151
152
|
const [year, month, day] = datePart.split("-").map(Number);
|
|
152
153
|
const [hour, minute, second] = timePart.split(":").map(Number);
|
|
153
154
|
let expirationHour = hour + TOKEN_EXPIRATION_HOURS;
|
|
@@ -38,6 +38,12 @@ interface RuntimeModuleOptions {
|
|
|
38
38
|
* @default '/reset-password'
|
|
39
39
|
*/
|
|
40
40
|
passwordResetUrl?: string;
|
|
41
|
+
/**
|
|
42
|
+
* URL to redirect to after email confirmation (success or failure)
|
|
43
|
+
* Query parameters will be added: ?status=success|error&message=...
|
|
44
|
+
* @default '/login'
|
|
45
|
+
*/
|
|
46
|
+
emailConfirmationUrl?: string;
|
|
41
47
|
/**
|
|
42
48
|
* Skip database checks during module setup to prevent hanging
|
|
43
49
|
* @default false
|
|
@@ -122,6 +128,7 @@ interface ModuleOptions {
|
|
|
122
128
|
};
|
|
123
129
|
mailer?: MailerOptions;
|
|
124
130
|
passwordResetUrl: string;
|
|
131
|
+
emailConfirmationUrl: string;
|
|
125
132
|
auth: {
|
|
126
133
|
whitelist: string[];
|
|
127
134
|
tokenExpiration: number;
|
|
@@ -38,6 +38,12 @@ interface RuntimeModuleOptions {
|
|
|
38
38
|
* @default '/reset-password'
|
|
39
39
|
*/
|
|
40
40
|
passwordResetUrl?: string;
|
|
41
|
+
/**
|
|
42
|
+
* URL to redirect to after email confirmation (success or failure)
|
|
43
|
+
* Query parameters will be added: ?status=success|error&message=...
|
|
44
|
+
* @default '/login'
|
|
45
|
+
*/
|
|
46
|
+
emailConfirmationUrl?: string;
|
|
41
47
|
/**
|
|
42
48
|
* Skip database checks during module setup to prevent hanging
|
|
43
49
|
* @default false
|
|
@@ -122,6 +128,7 @@ interface ModuleOptions {
|
|
|
122
128
|
};
|
|
123
129
|
mailer?: MailerOptions;
|
|
124
130
|
passwordResetUrl: string;
|
|
131
|
+
emailConfirmationUrl: string;
|
|
125
132
|
auth: {
|
|
126
133
|
whitelist: string[];
|
|
127
134
|
tokenExpiration: number;
|
package/dist/utils.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { g as DatabaseConfig, f as DatabaseType, D as DisplayFieldsProps, L as LoginFormData, c as LoginFormProps, M as ModuleOptions, b as PasswordResetToken, e as Permission, P as PersonalAccessToken, d as ResetPasswordFormProps, R as RuntimeModuleOptions, U as User, a as UserWithoutPassword, h as defaultDisplayFields, i as defaultFieldLabels } from './shared/nuxt-users.
|
|
1
|
+
export { g as DatabaseConfig, f as DatabaseType, D as DisplayFieldsProps, L as LoginFormData, c as LoginFormProps, M as ModuleOptions, b as PasswordResetToken, e as Permission, P as PersonalAccessToken, d as ResetPasswordFormProps, R as RuntimeModuleOptions, U as User, a as UserWithoutPassword, h as defaultDisplayFields, i as defaultFieldLabels } from './shared/nuxt-users.BOm7L39P.mjs';
|
|
2
2
|
|
|
3
3
|
interface PasswordValidationResult {
|
|
4
4
|
isValid: boolean;
|
package/dist/utils.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { g as DatabaseConfig, f as DatabaseType, D as DisplayFieldsProps, L as LoginFormData, c as LoginFormProps, M as ModuleOptions, b as PasswordResetToken, e as Permission, P as PersonalAccessToken, d as ResetPasswordFormProps, R as RuntimeModuleOptions, U as User, a as UserWithoutPassword, h as defaultDisplayFields, i as defaultFieldLabels } from './shared/nuxt-users.
|
|
1
|
+
export { g as DatabaseConfig, f as DatabaseType, D as DisplayFieldsProps, L as LoginFormData, c as LoginFormProps, M as ModuleOptions, b as PasswordResetToken, e as Permission, P as PersonalAccessToken, d as ResetPasswordFormProps, R as RuntimeModuleOptions, U as User, a as UserWithoutPassword, h as defaultDisplayFields, i as defaultFieldLabels } from './shared/nuxt-users.BOm7L39P.js';
|
|
2
2
|
|
|
3
3
|
interface PasswordValidationResult {
|
|
4
4
|
isValid: boolean;
|
package/package.json
CHANGED