nuxt-users 1.6.2 → 1.6.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.
- package/CHANGELOG.md +33 -0
- package/dist/cli.mjs +3 -4
- package/dist/module.d.mts +114 -1
- package/dist/module.d.ts +114 -1
- package/dist/module.json +1 -1
- package/dist/runtime/components/PasswordStrengthIndicator.vue.d.ts +1 -1
- package/dist/runtime/composables/usePasswordValidation.d.ts +1 -1
- package/dist/runtime/composables/usePasswordValidation.js +1 -1
- package/dist/runtime/plugin.js +1 -1
- package/dist/runtime/server/api/auth/reset-password.post.js +1 -1
- package/dist/runtime/server/api/login.post.js +1 -1
- package/dist/runtime/server/api/logout.get.js +1 -1
- package/dist/runtime/server/api/profile.get.js +1 -1
- package/dist/runtime/server/api/update-password.post.js +2 -1
- package/dist/runtime/server/services/password.js +1 -1
- package/dist/runtime/server/utils/create-migrations-table.d.ts +2 -0
- package/dist/runtime/server/utils/create-migrations-table.js +35 -0
- package/dist/runtime/server/utils/create-password-reset-tokens-table.d.ts +2 -0
- package/dist/runtime/server/utils/create-password-reset-tokens-table.js +40 -0
- package/dist/runtime/server/utils/create-personal-access-tokens-table.d.ts +2 -0
- package/dist/runtime/server/utils/create-personal-access-tokens-table.js +56 -0
- package/dist/runtime/server/utils/create-user.d.ts +1 -0
- package/dist/runtime/server/utils/create-user.js +1 -0
- package/dist/runtime/server/utils/create-users-table.d.ts +2 -0
- package/dist/runtime/server/utils/create-users-table.js +47 -0
- package/dist/runtime/server/utils/db.d.ts +4 -0
- package/dist/runtime/server/utils/db.js +46 -0
- package/dist/runtime/server/utils/index.d.ts +7 -0
- package/dist/runtime/server/utils/index.js +7 -0
- package/dist/runtime/server/utils/migrate.d.ts +4 -0
- package/dist/runtime/server/utils/migrate.js +63 -0
- package/dist/runtime/server/utils/user.d.ts +27 -0
- package/dist/runtime/server/utils/user.js +94 -0
- package/dist/utils.d.mts +1 -42
- package/dist/utils.d.ts +1 -42
- package/dist/utils.mjs +162 -3
- package/package.json +2 -1
- package/dist/shared/nuxt-users.CMEtv_Mw.d.mts +0 -124
- package/dist/shared/nuxt-users.CMEtv_Mw.d.ts +0 -124
- package/dist/shared/nuxt-users.C_UkhLJ9.mjs +0 -531
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { useDb, checkTableExists } from "./db.js";
|
|
2
|
+
export { createUser, findUserByEmail, updateUserPassword, getCurrentUserFromToken, hasAnyUsers } from "./user.js";
|
|
3
|
+
export { createUsersTable } from "./create-users-table.js";
|
|
4
|
+
export { createPersonalAccessTokensTable } from "./create-personal-access-tokens-table.js";
|
|
5
|
+
export { createPasswordResetTokensTable } from "./create-password-reset-tokens-table.js";
|
|
6
|
+
export { createMigrationsTable } from "./create-migrations-table.js";
|
|
7
|
+
export { runMigrations } from "./migrate.js";
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { ModuleOptions } from '../../../types.js';
|
|
2
|
+
export declare const getAppliedMigrations: (options: ModuleOptions) => Promise<string[]>;
|
|
3
|
+
export declare const markMigrationAsApplied: (options: ModuleOptions, migrationName: string) => Promise<void>;
|
|
4
|
+
export declare const runMigrations: (options: ModuleOptions) => Promise<void>;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { useDb } from "./db.js";
|
|
2
|
+
import { createUsersTable } from "./create-users-table.js";
|
|
3
|
+
import { createPersonalAccessTokensTable } from "./create-personal-access-tokens-table.js";
|
|
4
|
+
import { createPasswordResetTokensTable } from "./create-password-reset-tokens-table.js";
|
|
5
|
+
import { createMigrationsTable } from "./create-migrations-table.js";
|
|
6
|
+
const migrations = [
|
|
7
|
+
{
|
|
8
|
+
name: "create_migrations_table",
|
|
9
|
+
run: createMigrationsTable
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
name: "create_users_table",
|
|
13
|
+
run: createUsersTable
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
name: "create_personal_access_tokens_table",
|
|
17
|
+
run: createPersonalAccessTokensTable
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
name: "create_password_reset_tokens_table",
|
|
21
|
+
run: createPasswordResetTokensTable
|
|
22
|
+
}
|
|
23
|
+
];
|
|
24
|
+
export const getAppliedMigrations = async (options) => {
|
|
25
|
+
const db = await useDb(options);
|
|
26
|
+
try {
|
|
27
|
+
const result = await db.sql`SELECT name FROM migrations ORDER BY id`;
|
|
28
|
+
return result.rows.map((row) => row.name);
|
|
29
|
+
} catch {
|
|
30
|
+
return [];
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
export const markMigrationAsApplied = async (options, migrationName) => {
|
|
34
|
+
const db = await useDb(options);
|
|
35
|
+
await db.sql`INSERT INTO migrations (name) VALUES (${migrationName})`;
|
|
36
|
+
};
|
|
37
|
+
export const runMigrations = async (options) => {
|
|
38
|
+
console.log("[Nuxt Users] Starting migration system...");
|
|
39
|
+
await createMigrationsTable(options);
|
|
40
|
+
const appliedMigrations = await getAppliedMigrations(options);
|
|
41
|
+
console.log(`[Nuxt Users] Applied migrations: ${appliedMigrations.join(", ")}`);
|
|
42
|
+
const pendingMigrations = migrations.filter((migration) => !appliedMigrations.includes(migration.name));
|
|
43
|
+
if (pendingMigrations.length === 0) {
|
|
44
|
+
console.log("[Nuxt Users] No pending migrations to run.");
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
console.log(`[Nuxt Users] Found ${pendingMigrations.length} pending migrations:`);
|
|
48
|
+
pendingMigrations.forEach((migration) => {
|
|
49
|
+
console.log(`[Nuxt Users] - ${migration.name}`);
|
|
50
|
+
});
|
|
51
|
+
for (const migration of pendingMigrations) {
|
|
52
|
+
console.log(`[Nuxt Users] Running migration: ${migration.name}`);
|
|
53
|
+
try {
|
|
54
|
+
await migration.run(options);
|
|
55
|
+
await markMigrationAsApplied(options, migration.name);
|
|
56
|
+
console.log(`[Nuxt Users] \u2713 Migration ${migration.name} successfull \u2705`);
|
|
57
|
+
} catch (error) {
|
|
58
|
+
console.error(`[Nuxt Users] \u2717 Migration ${migration.name} failed:`, error);
|
|
59
|
+
throw error;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
console.log("[Nuxt Users] All migrations successfull \u2705");
|
|
63
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { ModuleOptions, User } from '../../../types.js';
|
|
2
|
+
interface CreateUserParams {
|
|
3
|
+
email: string;
|
|
4
|
+
name: string;
|
|
5
|
+
password: string;
|
|
6
|
+
role?: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Creates a new user in the database.
|
|
10
|
+
* Hashes the password before storing.
|
|
11
|
+
*/
|
|
12
|
+
export declare const createUser: (userData: CreateUserParams, options: ModuleOptions) => Promise<Omit<User, "password">>;
|
|
13
|
+
/**
|
|
14
|
+
* Finds a user by their email address.
|
|
15
|
+
*/
|
|
16
|
+
export declare const findUserByEmail: (email: string, options: ModuleOptions) => Promise<User | null>;
|
|
17
|
+
/**
|
|
18
|
+
* Updates a user's password.
|
|
19
|
+
* Hashes the new password before storing.
|
|
20
|
+
*/
|
|
21
|
+
export declare const updateUserPassword: (email: string, newPassword: string, options: ModuleOptions) => Promise<void>;
|
|
22
|
+
export declare const hasAnyUsers: (options: ModuleOptions) => Promise<boolean>;
|
|
23
|
+
/**
|
|
24
|
+
* Gets the current user from an authentication token.
|
|
25
|
+
*/
|
|
26
|
+
export declare const getCurrentUserFromToken: (token: string, options: ModuleOptions) => Promise<User | null>;
|
|
27
|
+
export {};
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { useDb } from "./db.js";
|
|
2
|
+
import bcrypt from "bcrypt";
|
|
3
|
+
import { validatePassword, getPasswordValidationOptions } from "../../../utils";
|
|
4
|
+
export const createUser = async (userData, options) => {
|
|
5
|
+
const db = await useDb(options);
|
|
6
|
+
const usersTable = options.tables.users;
|
|
7
|
+
const passwordOptions = getPasswordValidationOptions(options);
|
|
8
|
+
const passwordValidation = validatePassword(userData.password, passwordOptions);
|
|
9
|
+
if (!passwordValidation.isValid) {
|
|
10
|
+
throw new Error(`Password validation failed: ${passwordValidation.errors.join(", ")}`);
|
|
11
|
+
}
|
|
12
|
+
const hashedPassword = await bcrypt.hash(userData.password, 10);
|
|
13
|
+
const role = userData.role || "user";
|
|
14
|
+
await db.sql`
|
|
15
|
+
INSERT INTO {${usersTable}} (email, name, password, role, created_at, updated_at)
|
|
16
|
+
VALUES (${userData.email}, ${userData.name}, ${hashedPassword}, ${role}, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)
|
|
17
|
+
`;
|
|
18
|
+
const result = await db.sql`SELECT id, email, name, role, created_at, updated_at FROM {${usersTable}} WHERE email = ${userData.email}`;
|
|
19
|
+
if (result.rows.length === 0) {
|
|
20
|
+
throw new Error("Failed to retrieve created user.");
|
|
21
|
+
}
|
|
22
|
+
const user = result.rows[0];
|
|
23
|
+
return {
|
|
24
|
+
id: user.id,
|
|
25
|
+
email: user.email,
|
|
26
|
+
name: user.name,
|
|
27
|
+
role: user.role,
|
|
28
|
+
created_at: user.created_at instanceof Date ? user.created_at.toISOString() : user.created_at,
|
|
29
|
+
updated_at: user.updated_at instanceof Date ? user.updated_at.toISOString() : user.updated_at
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
export const findUserByEmail = async (email, options) => {
|
|
33
|
+
const db = await useDb(options);
|
|
34
|
+
const usersTable = options.tables.users;
|
|
35
|
+
const result = await db.sql`SELECT * FROM {${usersTable}} WHERE email = ${email}`;
|
|
36
|
+
if (result.rows.length === 0) {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
const user = result.rows[0];
|
|
40
|
+
return {
|
|
41
|
+
id: user.id,
|
|
42
|
+
email: user.email,
|
|
43
|
+
name: user.name,
|
|
44
|
+
password: user.password,
|
|
45
|
+
role: user.role,
|
|
46
|
+
created_at: user.created_at instanceof Date ? user.created_at.toISOString() : user.created_at,
|
|
47
|
+
updated_at: user.updated_at instanceof Date ? user.updated_at.toISOString() : user.updated_at
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
export const updateUserPassword = async (email, newPassword, options) => {
|
|
51
|
+
const db = await useDb(options);
|
|
52
|
+
const usersTable = options.tables.users;
|
|
53
|
+
const passwordOptions = getPasswordValidationOptions(options);
|
|
54
|
+
const passwordValidation = validatePassword(newPassword, passwordOptions);
|
|
55
|
+
if (!passwordValidation.isValid) {
|
|
56
|
+
throw new Error(`Password validation failed: ${passwordValidation.errors.join(", ")}`);
|
|
57
|
+
}
|
|
58
|
+
const hashedPassword = await bcrypt.hash(newPassword, 10);
|
|
59
|
+
await db.sql`
|
|
60
|
+
UPDATE {${usersTable}}
|
|
61
|
+
SET password = ${hashedPassword}, updated_at = CURRENT_TIMESTAMP
|
|
62
|
+
WHERE email = ${email}
|
|
63
|
+
`;
|
|
64
|
+
};
|
|
65
|
+
export const hasAnyUsers = async (options) => {
|
|
66
|
+
try {
|
|
67
|
+
const db = await useDb(options);
|
|
68
|
+
const users = await db.sql`SELECT COUNT(*) as count FROM {${options.tables.users}}`;
|
|
69
|
+
return users.rows?.[0]?.count > 0;
|
|
70
|
+
} catch {
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
export const getCurrentUserFromToken = async (token, options) => {
|
|
75
|
+
const db = await useDb(options);
|
|
76
|
+
const personalAccessTokensTable = options.tables.personalAccessTokens;
|
|
77
|
+
const usersTable = options.tables.users;
|
|
78
|
+
const tokenResult = await db.sql`
|
|
79
|
+
SELECT tokenable_id FROM {${personalAccessTokensTable}}
|
|
80
|
+
WHERE token = ${token}
|
|
81
|
+
`;
|
|
82
|
+
if (tokenResult.rows.length === 0) {
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
const userId = tokenResult.rows[0].tokenable_id;
|
|
86
|
+
const userResult = await db.sql`
|
|
87
|
+
SELECT * FROM {${usersTable}}
|
|
88
|
+
WHERE id = ${userId}
|
|
89
|
+
`;
|
|
90
|
+
if (userResult.rows.length === 0) {
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
return userResult.rows[0];
|
|
94
|
+
};
|
package/dist/utils.d.mts
CHANGED
|
@@ -1,44 +1,3 @@
|
|
|
1
|
-
import * as db0 from 'db0';
|
|
2
|
-
import { M as ModuleOptions, U as User } from './shared/nuxt-users.CMEtv_Mw.mjs';
|
|
3
|
-
|
|
4
|
-
declare const useDb: (options: ModuleOptions) => Promise<db0.Database<db0.Connector<Database.Database>>>;
|
|
5
|
-
declare const checkTableExists: (options: ModuleOptions, tableName: string) => Promise<boolean>;
|
|
6
|
-
|
|
7
|
-
interface CreateUserParams {
|
|
8
|
-
email: string;
|
|
9
|
-
name: string;
|
|
10
|
-
password: string;
|
|
11
|
-
role?: string;
|
|
12
|
-
}
|
|
13
|
-
/**
|
|
14
|
-
* Creates a new user in the database.
|
|
15
|
-
* Hashes the password before storing.
|
|
16
|
-
*/
|
|
17
|
-
declare const createUser: (userData: CreateUserParams, options: ModuleOptions) => Promise<Omit<User, "password">>;
|
|
18
|
-
/**
|
|
19
|
-
* Finds a user by their email address.
|
|
20
|
-
*/
|
|
21
|
-
declare const findUserByEmail: (email: string, options: ModuleOptions) => Promise<User | null>;
|
|
22
|
-
/**
|
|
23
|
-
* Updates a user's password.
|
|
24
|
-
* Hashes the new password before storing.
|
|
25
|
-
*/
|
|
26
|
-
declare const updateUserPassword: (email: string, newPassword: string, options: ModuleOptions) => Promise<void>;
|
|
27
|
-
/**
|
|
28
|
-
* Gets the current user from an authentication token.
|
|
29
|
-
*/
|
|
30
|
-
declare const getCurrentUserFromToken: (token: string, options: ModuleOptions) => Promise<User | null>;
|
|
31
|
-
|
|
32
|
-
declare const createUsersTable: (options: ModuleOptions) => Promise<void>;
|
|
33
|
-
|
|
34
|
-
declare const createPersonalAccessTokensTable: (options: ModuleOptions) => Promise<void>;
|
|
35
|
-
|
|
36
|
-
declare const createPasswordResetTokensTable: (options: ModuleOptions) => Promise<void>;
|
|
37
|
-
|
|
38
|
-
declare const createMigrationsTable: (options: ModuleOptions) => Promise<void>;
|
|
39
|
-
|
|
40
|
-
declare const runMigrations: (options: ModuleOptions) => Promise<void>;
|
|
41
|
-
|
|
42
1
|
interface PasswordValidationResult {
|
|
43
2
|
isValid: boolean;
|
|
44
3
|
errors: string[];
|
|
@@ -64,5 +23,5 @@ declare const validatePassword: (password: string, options?: PasswordValidationO
|
|
|
64
23
|
declare const getPasswordStrengthColor: (strength: "weak" | "medium" | "strong") => string;
|
|
65
24
|
declare const getPasswordStrengthText: (strength: "weak" | "medium" | "strong") => string;
|
|
66
25
|
|
|
67
|
-
export {
|
|
26
|
+
export { getPasswordStrengthColor, getPasswordStrengthText, getPasswordValidationOptions, validatePassword };
|
|
68
27
|
export type { PasswordValidationOptions, PasswordValidationResult };
|
package/dist/utils.d.ts
CHANGED
|
@@ -1,44 +1,3 @@
|
|
|
1
|
-
import * as db0 from 'db0';
|
|
2
|
-
import { M as ModuleOptions, U as User } from './shared/nuxt-users.CMEtv_Mw.js';
|
|
3
|
-
|
|
4
|
-
declare const useDb: (options: ModuleOptions) => Promise<db0.Database<db0.Connector<Database.Database>>>;
|
|
5
|
-
declare const checkTableExists: (options: ModuleOptions, tableName: string) => Promise<boolean>;
|
|
6
|
-
|
|
7
|
-
interface CreateUserParams {
|
|
8
|
-
email: string;
|
|
9
|
-
name: string;
|
|
10
|
-
password: string;
|
|
11
|
-
role?: string;
|
|
12
|
-
}
|
|
13
|
-
/**
|
|
14
|
-
* Creates a new user in the database.
|
|
15
|
-
* Hashes the password before storing.
|
|
16
|
-
*/
|
|
17
|
-
declare const createUser: (userData: CreateUserParams, options: ModuleOptions) => Promise<Omit<User, "password">>;
|
|
18
|
-
/**
|
|
19
|
-
* Finds a user by their email address.
|
|
20
|
-
*/
|
|
21
|
-
declare const findUserByEmail: (email: string, options: ModuleOptions) => Promise<User | null>;
|
|
22
|
-
/**
|
|
23
|
-
* Updates a user's password.
|
|
24
|
-
* Hashes the new password before storing.
|
|
25
|
-
*/
|
|
26
|
-
declare const updateUserPassword: (email: string, newPassword: string, options: ModuleOptions) => Promise<void>;
|
|
27
|
-
/**
|
|
28
|
-
* Gets the current user from an authentication token.
|
|
29
|
-
*/
|
|
30
|
-
declare const getCurrentUserFromToken: (token: string, options: ModuleOptions) => Promise<User | null>;
|
|
31
|
-
|
|
32
|
-
declare const createUsersTable: (options: ModuleOptions) => Promise<void>;
|
|
33
|
-
|
|
34
|
-
declare const createPersonalAccessTokensTable: (options: ModuleOptions) => Promise<void>;
|
|
35
|
-
|
|
36
|
-
declare const createPasswordResetTokensTable: (options: ModuleOptions) => Promise<void>;
|
|
37
|
-
|
|
38
|
-
declare const createMigrationsTable: (options: ModuleOptions) => Promise<void>;
|
|
39
|
-
|
|
40
|
-
declare const runMigrations: (options: ModuleOptions) => Promise<void>;
|
|
41
|
-
|
|
42
1
|
interface PasswordValidationResult {
|
|
43
2
|
isValid: boolean;
|
|
44
3
|
errors: string[];
|
|
@@ -64,5 +23,5 @@ declare const validatePassword: (password: string, options?: PasswordValidationO
|
|
|
64
23
|
declare const getPasswordStrengthColor: (strength: "weak" | "medium" | "strong") => string;
|
|
65
24
|
declare const getPasswordStrengthText: (strength: "weak" | "medium" | "strong") => string;
|
|
66
25
|
|
|
67
|
-
export {
|
|
26
|
+
export { getPasswordStrengthColor, getPasswordStrengthText, getPasswordValidationOptions, validatePassword };
|
|
68
27
|
export type { PasswordValidationOptions, PasswordValidationResult };
|
package/dist/utils.mjs
CHANGED
|
@@ -1,3 +1,162 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
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, getPasswordStrengthText, getPasswordValidationOptions, validatePassword };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nuxt-users",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.4",
|
|
4
4
|
"description": "A comprehensive user management module for Nuxt 3 applications with authentication, database support, and CLI tools",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"nuxt",
|
|
@@ -59,6 +59,7 @@
|
|
|
59
59
|
"dev:build": "nuxi build playground",
|
|
60
60
|
"dev:prepare": "yarn nuxt-module-build build --stub && yarn nuxt-module-build prepare && nuxi prepare playground",
|
|
61
61
|
"build": "node scripts/replace-version.js && nuxt-module-build build",
|
|
62
|
+
"postbuild": "node scripts/post-build.js",
|
|
62
63
|
"prerelease": "node -v | grep -q 'v22' || (echo 'Please use Node.js v22 for deployment' && exit 1)",
|
|
63
64
|
"release": "yarn lint && yarn test && yarn build && changelogen --release && yarn publish && git push --follow-tags",
|
|
64
65
|
"lint": "eslint .",
|
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
type DatabaseType = 'sqlite' | 'mysql' | 'postgresql';
|
|
2
|
-
type DatabaseConfig = {
|
|
3
|
-
path?: string;
|
|
4
|
-
host?: string;
|
|
5
|
-
port?: number;
|
|
6
|
-
user?: string;
|
|
7
|
-
password?: string;
|
|
8
|
-
database?: string;
|
|
9
|
-
};
|
|
10
|
-
interface RuntimeModuleOptions {
|
|
11
|
-
connector?: {
|
|
12
|
-
name: DatabaseType;
|
|
13
|
-
options: DatabaseConfig;
|
|
14
|
-
};
|
|
15
|
-
tables?: {
|
|
16
|
-
migrations?: string;
|
|
17
|
-
users?: string;
|
|
18
|
-
personalAccessTokens?: string;
|
|
19
|
-
passwordResetTokens?: string;
|
|
20
|
-
};
|
|
21
|
-
/**
|
|
22
|
-
* Mailer configuration options for sending emails (e.g., password resets)
|
|
23
|
-
* Uses nodemailer
|
|
24
|
-
*/
|
|
25
|
-
mailer?: MailerOptions;
|
|
26
|
-
/**
|
|
27
|
-
* Base URL for password reset links
|
|
28
|
-
* @default 'http://localhost:3000' // Example, will be set in module defaults
|
|
29
|
-
*/
|
|
30
|
-
passwordResetBaseUrl?: string;
|
|
31
|
-
/**
|
|
32
|
-
* Skip database checks during module setup to prevent hanging
|
|
33
|
-
* @default false
|
|
34
|
-
*/
|
|
35
|
-
auth?: {
|
|
36
|
-
/**
|
|
37
|
-
* Whitelisted routes that do not require authentication
|
|
38
|
-
* @default ['/login']
|
|
39
|
-
* @example ['/login', '/register']
|
|
40
|
-
*/
|
|
41
|
-
whitelist?: string[];
|
|
42
|
-
};
|
|
43
|
-
/**
|
|
44
|
-
* Password validation configuration
|
|
45
|
-
*/
|
|
46
|
-
passwordValidation?: {
|
|
47
|
-
/**
|
|
48
|
-
* Minimum password length
|
|
49
|
-
* @default 8
|
|
50
|
-
*/
|
|
51
|
-
minLength?: number;
|
|
52
|
-
/**
|
|
53
|
-
* Require uppercase letters
|
|
54
|
-
* @default true
|
|
55
|
-
*/
|
|
56
|
-
requireUppercase?: boolean;
|
|
57
|
-
/**
|
|
58
|
-
* Require lowercase letters
|
|
59
|
-
* @default true
|
|
60
|
-
*/
|
|
61
|
-
requireLowercase?: boolean;
|
|
62
|
-
/**
|
|
63
|
-
* Require numbers
|
|
64
|
-
* @default true
|
|
65
|
-
*/
|
|
66
|
-
requireNumbers?: boolean;
|
|
67
|
-
/**
|
|
68
|
-
* Require special characters
|
|
69
|
-
* @default true
|
|
70
|
-
*/
|
|
71
|
-
requireSpecialChars?: boolean;
|
|
72
|
-
/**
|
|
73
|
-
* Prevent common passwords
|
|
74
|
-
* @default true
|
|
75
|
-
*/
|
|
76
|
-
preventCommonPasswords?: boolean;
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
interface ModuleOptions extends Omit<RuntimeModuleOptions, 'tables' | 'auth' | 'passwordValidation'> {
|
|
80
|
-
connector: {
|
|
81
|
-
name: DatabaseType;
|
|
82
|
-
options: DatabaseConfig;
|
|
83
|
-
};
|
|
84
|
-
tables: {
|
|
85
|
-
migrations: string;
|
|
86
|
-
users: string;
|
|
87
|
-
personalAccessTokens: string;
|
|
88
|
-
passwordResetTokens: string;
|
|
89
|
-
};
|
|
90
|
-
auth: {
|
|
91
|
-
whitelist: string[];
|
|
92
|
-
};
|
|
93
|
-
passwordValidation: {
|
|
94
|
-
minLength: number;
|
|
95
|
-
requireUppercase: boolean;
|
|
96
|
-
requireLowercase: boolean;
|
|
97
|
-
requireNumbers: boolean;
|
|
98
|
-
requireSpecialChars: boolean;
|
|
99
|
-
preventCommonPasswords: boolean;
|
|
100
|
-
};
|
|
101
|
-
}
|
|
102
|
-
interface MailerOptions {
|
|
103
|
-
host: string;
|
|
104
|
-
port: number;
|
|
105
|
-
secure?: boolean;
|
|
106
|
-
auth: {
|
|
107
|
-
user: string;
|
|
108
|
-
pass: string;
|
|
109
|
-
};
|
|
110
|
-
defaults?: {
|
|
111
|
-
from: string;
|
|
112
|
-
};
|
|
113
|
-
}
|
|
114
|
-
interface User {
|
|
115
|
-
id: number;
|
|
116
|
-
email: string;
|
|
117
|
-
name: string;
|
|
118
|
-
password: string;
|
|
119
|
-
role: string;
|
|
120
|
-
created_at: string;
|
|
121
|
-
updated_at: string;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
export type { ModuleOptions as M, User as U };
|