nuxt-users 1.17.1 → 1.17.3
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 +39 -0
- package/dist/cli.mjs +12 -2
- package/dist/module.d.mts +1 -1
- package/dist/module.d.ts +1 -1
- package/dist/module.json +1 -1
- package/dist/runtime/components/NUsersList.vue +1 -1
- package/dist/runtime/components/NUsersUserCard.vue +1 -1
- package/dist/runtime/server/api/nuxt-users/password/forgot.post.js +4 -1
- package/dist/shared/{nuxt-users.CAfpTSaE.d.mts → nuxt-users.B8X7pDsj.d.mts} +26 -1
- package/dist/shared/{nuxt-users.CAfpTSaE.d.ts → nuxt-users.B8X7pDsj.d.ts} +26 -1
- package/dist/shared/nuxt-users.BnOQs2LI.mjs +162 -0
- package/dist/utils.d.mts +1 -1
- package/dist/utils.d.ts +1 -1
- package/dist/utils.mjs +13 -160
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,45 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
3
|
|
|
4
|
+
## v1.17.3
|
|
5
|
+
|
|
6
|
+
[compare changes](https://github.com/rrd108/nuxt-users/compare/v1.17.2...v1.17.3)
|
|
7
|
+
|
|
8
|
+
### 🩹 Fixes
|
|
9
|
+
|
|
10
|
+
- Cli version mismatch ([86d49c4](https://github.com/rrd108/nuxt-users/commit/86d49c4))
|
|
11
|
+
- Import paths and exports types ([16b5a28](https://github.com/rrd108/nuxt-users/commit/16b5a28))
|
|
12
|
+
- Cli version ([586194f](https://github.com/rrd108/nuxt-users/commit/586194f))
|
|
13
|
+
- Use runtime config for password reset link ([f462f64](https://github.com/rrd108/nuxt-users/commit/f462f64))
|
|
14
|
+
|
|
15
|
+
### 🏡 Chore
|
|
16
|
+
|
|
17
|
+
- **release:** V1.17.2 ([f640ba2](https://github.com/rrd108/nuxt-users/commit/f640ba2))
|
|
18
|
+
|
|
19
|
+
### ❤️ Contributors
|
|
20
|
+
|
|
21
|
+
- Rrd108 ([@rrd108](https://github.com/rrd108))
|
|
22
|
+
|
|
23
|
+
## v1.17.2
|
|
24
|
+
|
|
25
|
+
[compare changes](https://github.com/rrd108/nuxt-users/compare/v1.17.1...v1.17.2)
|
|
26
|
+
|
|
27
|
+
### 🩹 Fixes
|
|
28
|
+
|
|
29
|
+
- Component type import errors ([b1e7329](https://github.com/rrd108/nuxt-users/commit/b1e7329))
|
|
30
|
+
- Import errors ([3e7f99a](https://github.com/rrd108/nuxt-users/commit/3e7f99a))
|
|
31
|
+
- Cli version mismatch ([86d49c4](https://github.com/rrd108/nuxt-users/commit/86d49c4))
|
|
32
|
+
- Import paths and exports types ([16b5a28](https://github.com/rrd108/nuxt-users/commit/16b5a28))
|
|
33
|
+
|
|
34
|
+
### 🏡 Chore
|
|
35
|
+
|
|
36
|
+
- Bump version number ([7d48235](https://github.com/rrd108/nuxt-users/commit/7d48235))
|
|
37
|
+
- **release:** V1.17.1 ([d1ae8fd](https://github.com/rrd108/nuxt-users/commit/d1ae8fd))
|
|
38
|
+
|
|
39
|
+
### ❤️ Contributors
|
|
40
|
+
|
|
41
|
+
- Rrd108 ([@rrd108](https://github.com/rrd108))
|
|
42
|
+
|
|
4
43
|
## v1.17.1
|
|
5
44
|
|
|
6
45
|
[compare changes](https://github.com/rrd108/nuxt-users/compare/v1.17.0...v1.17.1)
|
package/dist/cli.mjs
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { defineCommand, runMain } from 'citty';
|
|
3
|
+
import { readFileSync } from 'node:fs';
|
|
3
4
|
import { defaultOptions } from './module.mjs';
|
|
4
5
|
import { loadNuxt } from '@nuxt/kit';
|
|
5
6
|
import { defu } from 'defu';
|
|
6
7
|
import { runMigrations, createUser as createUser$1, createUsersTable as createUsersTable$1, createPersonalAccessTokensTable as createPersonalAccessTokensTable$1, createPasswordResetTokensTable as createPasswordResetTokensTable$1, createMigrationsTable as createMigrationsTable$1 } from '../dist/runtime/server/utils/index.js';
|
|
7
|
-
import { getPasswordValidationOptions, validatePassword } from './
|
|
8
|
+
import { g as getPasswordValidationOptions, v as validatePassword } from './shared/nuxt-users.BnOQs2LI.mjs';
|
|
8
9
|
import { addActiveToUsers as addActiveToUsers$1 } from '../dist/runtime/server/utils/add-active-to-users.js';
|
|
9
10
|
import '../dist/runtime/server/internal/index.js';
|
|
10
11
|
|
|
@@ -263,11 +264,20 @@ const projectInfo = defineCommand({
|
|
|
263
264
|
}
|
|
264
265
|
});
|
|
265
266
|
|
|
267
|
+
const getVersion = () => {
|
|
268
|
+
try {
|
|
269
|
+
const packagePath = new URL("../package.json", import.meta.url);
|
|
270
|
+
const packageJson = JSON.parse(readFileSync(packagePath, "utf8"));
|
|
271
|
+
return packageJson.version;
|
|
272
|
+
} catch {
|
|
273
|
+
return "unknown";
|
|
274
|
+
}
|
|
275
|
+
};
|
|
266
276
|
const main = defineCommand({
|
|
267
277
|
meta: {
|
|
268
278
|
name: "nuxt-users",
|
|
269
279
|
description: "CLI for Nuxt Users Module - Manage users, migrations, and database operations",
|
|
270
|
-
version:
|
|
280
|
+
version: getVersion()
|
|
271
281
|
},
|
|
272
282
|
subCommands: {
|
|
273
283
|
migrate,
|
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.B8X7pDsj.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.B8X7pDsj.js';
|
|
3
3
|
export * from '../dist/runtime/server/internal/index.js';
|
|
4
4
|
|
|
5
5
|
declare const defaultOptions: ModuleOptions;
|
package/dist/module.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script setup>
|
|
2
2
|
import { ref, onMounted } from "vue";
|
|
3
3
|
import { useRuntimeConfig } from "#imports";
|
|
4
|
-
import { defaultDisplayFields, defaultFieldLabels } from "
|
|
4
|
+
import { defaultDisplayFields, defaultFieldLabels } from "nuxt-users/utils";
|
|
5
5
|
defineProps({
|
|
6
6
|
displayFields: { type: Array, required: false, default: () => defaultDisplayFields },
|
|
7
7
|
fieldLabels: { type: Object, required: false, default: () => defaultFieldLabels }
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { computed } from "vue";
|
|
3
3
|
import { useAuthentication } from "../composables/useAuthentication";
|
|
4
4
|
import { useRuntimeConfig } from "#imports";
|
|
5
|
-
import { defaultDisplayFields, defaultFieldLabels } from "
|
|
5
|
+
import { defaultDisplayFields, defaultFieldLabels } from "nuxt-users/utils";
|
|
6
6
|
const props = defineProps({
|
|
7
7
|
user: { type: Object, required: true },
|
|
8
8
|
index: { type: Number, required: true },
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { defineEventHandler, readBody, createError } from "h3";
|
|
2
2
|
import { sendPasswordResetLink } from "../../../services/password.js";
|
|
3
|
+
import { useRuntimeConfig } from "#imports";
|
|
3
4
|
export default defineEventHandler(async (event) => {
|
|
5
|
+
const { nuxtUsers } = useRuntimeConfig();
|
|
6
|
+
const options = nuxtUsers;
|
|
4
7
|
const body = await readBody(event);
|
|
5
8
|
const { email } = body;
|
|
6
9
|
if (!email || typeof email !== "string") {
|
|
@@ -10,7 +13,7 @@ export default defineEventHandler(async (event) => {
|
|
|
10
13
|
});
|
|
11
14
|
}
|
|
12
15
|
try {
|
|
13
|
-
await sendPasswordResetLink(email,
|
|
16
|
+
await sendPasswordResetLink(email, options);
|
|
14
17
|
return { message: "If a user with that email exists, a password reset link has been sent." };
|
|
15
18
|
} catch (error) {
|
|
16
19
|
if (error instanceof Error) {
|
|
@@ -176,5 +176,30 @@ interface LoginFormData {
|
|
|
176
176
|
password: string;
|
|
177
177
|
rememberMe?: boolean;
|
|
178
178
|
}
|
|
179
|
+
interface LoginFormProps {
|
|
180
|
+
apiEndpoint?: string;
|
|
181
|
+
redirectTo?: string;
|
|
182
|
+
forgotPasswordEndpoint?: string;
|
|
183
|
+
}
|
|
184
|
+
interface ResetPasswordFormProps {
|
|
185
|
+
apiEndpoint?: string;
|
|
186
|
+
updatePasswordEndpoint?: string;
|
|
187
|
+
}
|
|
188
|
+
interface DisplayFieldsProps {
|
|
189
|
+
displayFields?: string[];
|
|
190
|
+
fieldLabels?: Record<string, string>;
|
|
191
|
+
}
|
|
192
|
+
declare const defaultDisplayFields: string[];
|
|
193
|
+
declare const defaultFieldLabels: {
|
|
194
|
+
id: string;
|
|
195
|
+
name: string;
|
|
196
|
+
email: string;
|
|
197
|
+
role: string;
|
|
198
|
+
active: string;
|
|
199
|
+
created_at: string;
|
|
200
|
+
updated_at: string;
|
|
201
|
+
last_login_at: string;
|
|
202
|
+
};
|
|
179
203
|
|
|
180
|
-
export
|
|
204
|
+
export { defaultDisplayFields as e, defaultFieldLabels as f };
|
|
205
|
+
export type { DisplayFieldsProps as D, LoginFormData as L, ModuleOptions as M, PersonalAccessToken as P, RuntimeModuleOptions as R, User as U, UserWithoutPassword as a, PasswordResetToken as b, LoginFormProps as c, ResetPasswordFormProps as d };
|
|
@@ -176,5 +176,30 @@ interface LoginFormData {
|
|
|
176
176
|
password: string;
|
|
177
177
|
rememberMe?: boolean;
|
|
178
178
|
}
|
|
179
|
+
interface LoginFormProps {
|
|
180
|
+
apiEndpoint?: string;
|
|
181
|
+
redirectTo?: string;
|
|
182
|
+
forgotPasswordEndpoint?: string;
|
|
183
|
+
}
|
|
184
|
+
interface ResetPasswordFormProps {
|
|
185
|
+
apiEndpoint?: string;
|
|
186
|
+
updatePasswordEndpoint?: string;
|
|
187
|
+
}
|
|
188
|
+
interface DisplayFieldsProps {
|
|
189
|
+
displayFields?: string[];
|
|
190
|
+
fieldLabels?: Record<string, string>;
|
|
191
|
+
}
|
|
192
|
+
declare const defaultDisplayFields: string[];
|
|
193
|
+
declare const defaultFieldLabels: {
|
|
194
|
+
id: string;
|
|
195
|
+
name: string;
|
|
196
|
+
email: string;
|
|
197
|
+
role: string;
|
|
198
|
+
active: string;
|
|
199
|
+
created_at: string;
|
|
200
|
+
updated_at: string;
|
|
201
|
+
last_login_at: string;
|
|
202
|
+
};
|
|
179
203
|
|
|
180
|
-
export
|
|
204
|
+
export { defaultDisplayFields as e, defaultFieldLabels as f };
|
|
205
|
+
export type { DisplayFieldsProps as D, LoginFormData as L, ModuleOptions as M, PersonalAccessToken as P, RuntimeModuleOptions as R, User as U, UserWithoutPassword as a, PasswordResetToken as b, LoginFormProps as c, ResetPasswordFormProps as d };
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
const DEFAULT_OPTIONS = {
|
|
2
|
+
minLength: 8,
|
|
3
|
+
requireUppercase: true,
|
|
4
|
+
requireLowercase: true,
|
|
5
|
+
requireNumbers: true,
|
|
6
|
+
requireSpecialChars: true,
|
|
7
|
+
preventCommonPasswords: true
|
|
8
|
+
};
|
|
9
|
+
const getPasswordValidationOptions = (moduleOptions) => {
|
|
10
|
+
if (!moduleOptions?.passwordValidation) {
|
|
11
|
+
return DEFAULT_OPTIONS;
|
|
12
|
+
}
|
|
13
|
+
return {
|
|
14
|
+
...DEFAULT_OPTIONS,
|
|
15
|
+
...moduleOptions.passwordValidation
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
const COMMON_PASSWORDS = [
|
|
19
|
+
"password",
|
|
20
|
+
"123456",
|
|
21
|
+
"123456789",
|
|
22
|
+
"qwerty",
|
|
23
|
+
"abc123",
|
|
24
|
+
"password123",
|
|
25
|
+
"admin",
|
|
26
|
+
"letmein",
|
|
27
|
+
"welcome",
|
|
28
|
+
"monkey",
|
|
29
|
+
"dragon",
|
|
30
|
+
"master",
|
|
31
|
+
"hello",
|
|
32
|
+
"freedom",
|
|
33
|
+
"whatever",
|
|
34
|
+
"qazwsx",
|
|
35
|
+
"trustno1",
|
|
36
|
+
"jordan",
|
|
37
|
+
"harley",
|
|
38
|
+
"ranger",
|
|
39
|
+
"buster",
|
|
40
|
+
"thomas",
|
|
41
|
+
"tigger",
|
|
42
|
+
"robert",
|
|
43
|
+
"soccer",
|
|
44
|
+
"batman",
|
|
45
|
+
"test",
|
|
46
|
+
"pass",
|
|
47
|
+
"user",
|
|
48
|
+
"guest",
|
|
49
|
+
"login",
|
|
50
|
+
"secret",
|
|
51
|
+
"god",
|
|
52
|
+
"love",
|
|
53
|
+
"sex",
|
|
54
|
+
"money",
|
|
55
|
+
"password1",
|
|
56
|
+
"12345678",
|
|
57
|
+
"qwerty123",
|
|
58
|
+
"admin123",
|
|
59
|
+
"password!",
|
|
60
|
+
"password1!",
|
|
61
|
+
"password123",
|
|
62
|
+
"password123!"
|
|
63
|
+
];
|
|
64
|
+
const validatePassword = (password, options = {}) => {
|
|
65
|
+
const config = { ...DEFAULT_OPTIONS, ...options };
|
|
66
|
+
const errors = [];
|
|
67
|
+
const hints = [];
|
|
68
|
+
let score = 0;
|
|
69
|
+
if (password.length < config.minLength) {
|
|
70
|
+
errors.push(`Password must be at least ${config.minLength} characters long`);
|
|
71
|
+
hints.push(`Use at least ${config.minLength} characters`);
|
|
72
|
+
} else {
|
|
73
|
+
score += 20;
|
|
74
|
+
if (password.length < 12) {
|
|
75
|
+
hints.push("Use 12 or more characters for extra security");
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
if (config.requireUppercase && !/[A-Z]/.test(password)) {
|
|
79
|
+
errors.push("Password must contain at least one uppercase letter");
|
|
80
|
+
hints.push("Add an uppercase letter (A-Z)");
|
|
81
|
+
} else if (/[A-Z]/.test(password)) {
|
|
82
|
+
score += 15;
|
|
83
|
+
}
|
|
84
|
+
if (config.requireLowercase && !/[a-z]/.test(password)) {
|
|
85
|
+
errors.push("Password must contain at least one lowercase letter");
|
|
86
|
+
hints.push("Add a lowercase letter (a-z)");
|
|
87
|
+
} else if (/[a-z]/.test(password)) {
|
|
88
|
+
score += 15;
|
|
89
|
+
}
|
|
90
|
+
if (config.requireNumbers && !/\d/.test(password)) {
|
|
91
|
+
errors.push("Password must contain at least one number");
|
|
92
|
+
hints.push("Add a number (0-9)");
|
|
93
|
+
} else if (/\d/.test(password)) {
|
|
94
|
+
score += 15;
|
|
95
|
+
}
|
|
96
|
+
if (config.requireSpecialChars && !/[!@#$%^&*()_+\-=[\]{};':"\\|,.<>/?]/.test(password)) {
|
|
97
|
+
errors.push("Password must contain at least one special character");
|
|
98
|
+
hints.push("Add a special character (e.g. !@#$%)");
|
|
99
|
+
} else if (/[!@#$%^&*()_+\-=[\]{};':"\\|,.<>/?]/.test(password)) {
|
|
100
|
+
score += 15;
|
|
101
|
+
}
|
|
102
|
+
if (config.preventCommonPasswords && COMMON_PASSWORDS.includes(password.toLowerCase())) {
|
|
103
|
+
errors.push("Password is too common. Please choose a more unique password");
|
|
104
|
+
hints.push("Avoid common passwords or names");
|
|
105
|
+
}
|
|
106
|
+
if (password.length >= 12) {
|
|
107
|
+
score += 10;
|
|
108
|
+
} else if (password.length >= 10) {
|
|
109
|
+
score += 5;
|
|
110
|
+
}
|
|
111
|
+
const hasUppercase = /[A-Z]/.test(password);
|
|
112
|
+
const hasLowercase = /[a-z]/.test(password);
|
|
113
|
+
const hasNumbers = /\d/.test(password);
|
|
114
|
+
const hasSpecial = /[!@#$%^&*()_+\-=[\]{};':"\\|,.<>/?]/.test(password);
|
|
115
|
+
const complexityTypes = [hasUppercase, hasLowercase, hasNumbers, hasSpecial].filter(Boolean).length;
|
|
116
|
+
if (complexityTypes >= 4) {
|
|
117
|
+
score += 10;
|
|
118
|
+
} else if (complexityTypes >= 3) {
|
|
119
|
+
score += 5;
|
|
120
|
+
hints.push("Use a mix of uppercase, lowercase, numbers, and special characters");
|
|
121
|
+
}
|
|
122
|
+
let strength = "weak";
|
|
123
|
+
if (score >= 80) {
|
|
124
|
+
strength = "strong";
|
|
125
|
+
} else if (score >= 60) {
|
|
126
|
+
strength = "medium";
|
|
127
|
+
}
|
|
128
|
+
return {
|
|
129
|
+
isValid: errors.length === 0,
|
|
130
|
+
errors,
|
|
131
|
+
strength,
|
|
132
|
+
score: Math.min(score, 100),
|
|
133
|
+
hints: Array.from(new Set(hints))
|
|
134
|
+
// deduplicate
|
|
135
|
+
};
|
|
136
|
+
};
|
|
137
|
+
const getPasswordStrengthColor = (strength) => {
|
|
138
|
+
switch (strength) {
|
|
139
|
+
case "weak":
|
|
140
|
+
return "#dc3545";
|
|
141
|
+
case "medium":
|
|
142
|
+
return "#ffc107";
|
|
143
|
+
case "strong":
|
|
144
|
+
return "#28a745";
|
|
145
|
+
default:
|
|
146
|
+
return "#6c757d";
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
const getPasswordStrengthText = (strength) => {
|
|
150
|
+
switch (strength) {
|
|
151
|
+
case "weak":
|
|
152
|
+
return "Weak";
|
|
153
|
+
case "medium":
|
|
154
|
+
return "Medium";
|
|
155
|
+
case "strong":
|
|
156
|
+
return "Strong";
|
|
157
|
+
default:
|
|
158
|
+
return "Unknown";
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
export { getPasswordStrengthColor as a, getPasswordStrengthText as b, getPasswordValidationOptions as g, validatePassword as v };
|
package/dist/utils.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { L as LoginFormData, M as ModuleOptions, b as PasswordResetToken, P as PersonalAccessToken, U as User, a as UserWithoutPassword } from './shared/nuxt-users.
|
|
1
|
+
export { D as DisplayFieldsProps, L as LoginFormData, c as LoginFormProps, M as ModuleOptions, b as PasswordResetToken, P as PersonalAccessToken, d as ResetPasswordFormProps, R as RuntimeModuleOptions, U as User, a as UserWithoutPassword, e as defaultDisplayFields, f as defaultFieldLabels } from './shared/nuxt-users.B8X7pDsj.mjs';
|
|
2
2
|
|
|
3
3
|
interface PasswordValidationResult {
|
|
4
4
|
isValid: boolean;
|
package/dist/utils.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { L as LoginFormData, M as ModuleOptions, b as PasswordResetToken, P as PersonalAccessToken, U as User, a as UserWithoutPassword } from './shared/nuxt-users.
|
|
1
|
+
export { D as DisplayFieldsProps, L as LoginFormData, c as LoginFormProps, M as ModuleOptions, b as PasswordResetToken, P as PersonalAccessToken, d as ResetPasswordFormProps, R as RuntimeModuleOptions, U as User, a as UserWithoutPassword, e as defaultDisplayFields, f as defaultFieldLabels } from './shared/nuxt-users.B8X7pDsj.js';
|
|
2
2
|
|
|
3
3
|
interface PasswordValidationResult {
|
|
4
4
|
isValid: boolean;
|
package/dist/utils.mjs
CHANGED
|
@@ -1,162 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
return {
|
|
14
|
-
...DEFAULT_OPTIONS,
|
|
15
|
-
...moduleOptions.passwordValidation
|
|
16
|
-
};
|
|
17
|
-
};
|
|
18
|
-
const COMMON_PASSWORDS = [
|
|
19
|
-
"password",
|
|
20
|
-
"123456",
|
|
21
|
-
"123456789",
|
|
22
|
-
"qwerty",
|
|
23
|
-
"abc123",
|
|
24
|
-
"password123",
|
|
25
|
-
"admin",
|
|
26
|
-
"letmein",
|
|
27
|
-
"welcome",
|
|
28
|
-
"monkey",
|
|
29
|
-
"dragon",
|
|
30
|
-
"master",
|
|
31
|
-
"hello",
|
|
32
|
-
"freedom",
|
|
33
|
-
"whatever",
|
|
34
|
-
"qazwsx",
|
|
35
|
-
"trustno1",
|
|
36
|
-
"jordan",
|
|
37
|
-
"harley",
|
|
38
|
-
"ranger",
|
|
39
|
-
"buster",
|
|
40
|
-
"thomas",
|
|
41
|
-
"tigger",
|
|
42
|
-
"robert",
|
|
43
|
-
"soccer",
|
|
44
|
-
"batman",
|
|
45
|
-
"test",
|
|
46
|
-
"pass",
|
|
47
|
-
"user",
|
|
48
|
-
"guest",
|
|
49
|
-
"login",
|
|
50
|
-
"secret",
|
|
51
|
-
"god",
|
|
52
|
-
"love",
|
|
53
|
-
"sex",
|
|
54
|
-
"money",
|
|
55
|
-
"password1",
|
|
56
|
-
"12345678",
|
|
57
|
-
"qwerty123",
|
|
58
|
-
"admin123",
|
|
59
|
-
"password!",
|
|
60
|
-
"password1!",
|
|
61
|
-
"password123",
|
|
62
|
-
"password123!"
|
|
63
|
-
];
|
|
64
|
-
const validatePassword = (password, options = {}) => {
|
|
65
|
-
const config = { ...DEFAULT_OPTIONS, ...options };
|
|
66
|
-
const errors = [];
|
|
67
|
-
const hints = [];
|
|
68
|
-
let score = 0;
|
|
69
|
-
if (password.length < config.minLength) {
|
|
70
|
-
errors.push(`Password must be at least ${config.minLength} characters long`);
|
|
71
|
-
hints.push(`Use at least ${config.minLength} characters`);
|
|
72
|
-
} else {
|
|
73
|
-
score += 20;
|
|
74
|
-
if (password.length < 12) {
|
|
75
|
-
hints.push("Use 12 or more characters for extra security");
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
if (config.requireUppercase && !/[A-Z]/.test(password)) {
|
|
79
|
-
errors.push("Password must contain at least one uppercase letter");
|
|
80
|
-
hints.push("Add an uppercase letter (A-Z)");
|
|
81
|
-
} else if (/[A-Z]/.test(password)) {
|
|
82
|
-
score += 15;
|
|
83
|
-
}
|
|
84
|
-
if (config.requireLowercase && !/[a-z]/.test(password)) {
|
|
85
|
-
errors.push("Password must contain at least one lowercase letter");
|
|
86
|
-
hints.push("Add a lowercase letter (a-z)");
|
|
87
|
-
} else if (/[a-z]/.test(password)) {
|
|
88
|
-
score += 15;
|
|
89
|
-
}
|
|
90
|
-
if (config.requireNumbers && !/\d/.test(password)) {
|
|
91
|
-
errors.push("Password must contain at least one number");
|
|
92
|
-
hints.push("Add a number (0-9)");
|
|
93
|
-
} else if (/\d/.test(password)) {
|
|
94
|
-
score += 15;
|
|
95
|
-
}
|
|
96
|
-
if (config.requireSpecialChars && !/[!@#$%^&*()_+\-=[\]{};':"\\|,.<>/?]/.test(password)) {
|
|
97
|
-
errors.push("Password must contain at least one special character");
|
|
98
|
-
hints.push("Add a special character (e.g. !@#$%)");
|
|
99
|
-
} else if (/[!@#$%^&*()_+\-=[\]{};':"\\|,.<>/?]/.test(password)) {
|
|
100
|
-
score += 15;
|
|
101
|
-
}
|
|
102
|
-
if (config.preventCommonPasswords && COMMON_PASSWORDS.includes(password.toLowerCase())) {
|
|
103
|
-
errors.push("Password is too common. Please choose a more unique password");
|
|
104
|
-
hints.push("Avoid common passwords or names");
|
|
105
|
-
}
|
|
106
|
-
if (password.length >= 12) {
|
|
107
|
-
score += 10;
|
|
108
|
-
} else if (password.length >= 10) {
|
|
109
|
-
score += 5;
|
|
110
|
-
}
|
|
111
|
-
const hasUppercase = /[A-Z]/.test(password);
|
|
112
|
-
const hasLowercase = /[a-z]/.test(password);
|
|
113
|
-
const hasNumbers = /\d/.test(password);
|
|
114
|
-
const hasSpecial = /[!@#$%^&*()_+\-=[\]{};':"\\|,.<>/?]/.test(password);
|
|
115
|
-
const complexityTypes = [hasUppercase, hasLowercase, hasNumbers, hasSpecial].filter(Boolean).length;
|
|
116
|
-
if (complexityTypes >= 4) {
|
|
117
|
-
score += 10;
|
|
118
|
-
} else if (complexityTypes >= 3) {
|
|
119
|
-
score += 5;
|
|
120
|
-
hints.push("Use a mix of uppercase, lowercase, numbers, and special characters");
|
|
121
|
-
}
|
|
122
|
-
let strength = "weak";
|
|
123
|
-
if (score >= 80) {
|
|
124
|
-
strength = "strong";
|
|
125
|
-
} else if (score >= 60) {
|
|
126
|
-
strength = "medium";
|
|
127
|
-
}
|
|
128
|
-
return {
|
|
129
|
-
isValid: errors.length === 0,
|
|
130
|
-
errors,
|
|
131
|
-
strength,
|
|
132
|
-
score: Math.min(score, 100),
|
|
133
|
-
hints: Array.from(new Set(hints))
|
|
134
|
-
// deduplicate
|
|
135
|
-
};
|
|
136
|
-
};
|
|
137
|
-
const getPasswordStrengthColor = (strength) => {
|
|
138
|
-
switch (strength) {
|
|
139
|
-
case "weak":
|
|
140
|
-
return "#dc3545";
|
|
141
|
-
case "medium":
|
|
142
|
-
return "#ffc107";
|
|
143
|
-
case "strong":
|
|
144
|
-
return "#28a745";
|
|
145
|
-
default:
|
|
146
|
-
return "#6c757d";
|
|
147
|
-
}
|
|
148
|
-
};
|
|
149
|
-
const getPasswordStrengthText = (strength) => {
|
|
150
|
-
switch (strength) {
|
|
151
|
-
case "weak":
|
|
152
|
-
return "Weak";
|
|
153
|
-
case "medium":
|
|
154
|
-
return "Medium";
|
|
155
|
-
case "strong":
|
|
156
|
-
return "Strong";
|
|
157
|
-
default:
|
|
158
|
-
return "Unknown";
|
|
159
|
-
}
|
|
1
|
+
export { a as getPasswordStrengthColor, b as getPasswordStrengthText, g as getPasswordValidationOptions, v as validatePassword } from './shared/nuxt-users.BnOQs2LI.mjs';
|
|
2
|
+
|
|
3
|
+
const defaultDisplayFields = ["id", "name", "email", "role", "active", "created_at", "updated_at", "last_login_at"];
|
|
4
|
+
const defaultFieldLabels = {
|
|
5
|
+
id: "ID",
|
|
6
|
+
name: "Name",
|
|
7
|
+
email: "Email",
|
|
8
|
+
role: "Role",
|
|
9
|
+
active: "Active",
|
|
10
|
+
created_at: "Created",
|
|
11
|
+
updated_at: "Updated",
|
|
12
|
+
last_login_at: "Last Login"
|
|
160
13
|
};
|
|
161
14
|
|
|
162
|
-
export {
|
|
15
|
+
export { defaultDisplayFields, defaultFieldLabels };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nuxt-users",
|
|
3
|
-
"version": "1.17.
|
|
3
|
+
"version": "1.17.3",
|
|
4
4
|
"description": "A comprehensive user management module for Nuxt 3 and Nuxt 4 applications with authentication, authorization, database support, and CLI tools",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"nuxt",
|
|
@@ -59,10 +59,10 @@
|
|
|
59
59
|
"dev": "yarn dev:prepare && nuxi dev playground",
|
|
60
60
|
"dev:build": "nuxi build playground",
|
|
61
61
|
"dev:prepare": "yarn nuxt-module-build build --stub && yarn nuxt-module-build prepare && nuxi prepare playground",
|
|
62
|
-
"build": "
|
|
62
|
+
"build": "nuxt-module-build build",
|
|
63
63
|
"postbuild": "node scripts/post-build.js",
|
|
64
64
|
"prerelease": "node -v | grep -q 'v22' || (echo 'Please use Node.js v22 for deployment' && exit 1)",
|
|
65
|
-
"release": "yarn lint && yarn test &&
|
|
65
|
+
"release": "yarn lint && yarn test && changelogen --release && yarn build && yarn publish && git push --follow-tags",
|
|
66
66
|
"lint": "eslint .",
|
|
67
67
|
"lint:fix": "eslint . --fix",
|
|
68
68
|
"pretest": "node -v | grep -q 'v22' || (echo 'Please use Node.js v22 for testing' && exit 1)",
|