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
|
@@ -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 };
|
|
@@ -1,531 +0,0 @@
|
|
|
1
|
-
import bcrypt from 'bcrypt';
|
|
2
|
-
import { createDatabase } from 'db0';
|
|
3
|
-
|
|
4
|
-
const getConnector = async (name) => {
|
|
5
|
-
try {
|
|
6
|
-
switch (name) {
|
|
7
|
-
case "mysql":
|
|
8
|
-
return (await import('db0/connectors/mysql2')).default;
|
|
9
|
-
case "postgresql":
|
|
10
|
-
return (await import('db0/connectors/postgresql')).default;
|
|
11
|
-
case "sqlite":
|
|
12
|
-
return (await import('db0/connectors/better-sqlite3')).default;
|
|
13
|
-
default:
|
|
14
|
-
throw new Error(`Unsupported database connector: ${name}`);
|
|
15
|
-
}
|
|
16
|
-
} catch (error) {
|
|
17
|
-
if (error instanceof Error && error.message.includes("Cannot resolve")) {
|
|
18
|
-
throw new Error(`Database connector "${name}" not found. Please install the required peer dependency:
|
|
19
|
-
- For sqlite: yarn add better-sqlite3
|
|
20
|
-
- For mysql: yarn add mysql2
|
|
21
|
-
- For postgresql: yarn add pg`);
|
|
22
|
-
}
|
|
23
|
-
throw error;
|
|
24
|
-
}
|
|
25
|
-
};
|
|
26
|
-
const useDb = async (options) => {
|
|
27
|
-
const connectorName = options.connector.name;
|
|
28
|
-
const connector = await getConnector(connectorName);
|
|
29
|
-
const connectorOptions = { ...options.connector.options };
|
|
30
|
-
if (connectorName !== "sqlite") {
|
|
31
|
-
delete connectorOptions.path;
|
|
32
|
-
}
|
|
33
|
-
try {
|
|
34
|
-
return createDatabase(connector(connectorOptions));
|
|
35
|
-
} catch (error) {
|
|
36
|
-
console.warn(`[Nuxt Users] \u26A0\uFE0F Failed to connect to ${connectorName} database:`, error instanceof Error ? error.message : "Unknown error");
|
|
37
|
-
throw error;
|
|
38
|
-
}
|
|
39
|
-
};
|
|
40
|
-
const checkTableExists = async (options, tableName) => {
|
|
41
|
-
try {
|
|
42
|
-
const db = await useDb(options);
|
|
43
|
-
await db.sql`SELECT 1 FROM {${tableName}} LIMIT 1`;
|
|
44
|
-
return true;
|
|
45
|
-
} catch {
|
|
46
|
-
return false;
|
|
47
|
-
}
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
const DEFAULT_OPTIONS = {
|
|
51
|
-
minLength: 8,
|
|
52
|
-
requireUppercase: true,
|
|
53
|
-
requireLowercase: true,
|
|
54
|
-
requireNumbers: true,
|
|
55
|
-
requireSpecialChars: true,
|
|
56
|
-
preventCommonPasswords: true
|
|
57
|
-
};
|
|
58
|
-
const getPasswordValidationOptions = (moduleOptions) => {
|
|
59
|
-
if (!moduleOptions?.passwordValidation) {
|
|
60
|
-
return DEFAULT_OPTIONS;
|
|
61
|
-
}
|
|
62
|
-
return {
|
|
63
|
-
...DEFAULT_OPTIONS,
|
|
64
|
-
...moduleOptions.passwordValidation
|
|
65
|
-
};
|
|
66
|
-
};
|
|
67
|
-
const COMMON_PASSWORDS = [
|
|
68
|
-
"password",
|
|
69
|
-
"123456",
|
|
70
|
-
"123456789",
|
|
71
|
-
"qwerty",
|
|
72
|
-
"abc123",
|
|
73
|
-
"password123",
|
|
74
|
-
"admin",
|
|
75
|
-
"letmein",
|
|
76
|
-
"welcome",
|
|
77
|
-
"monkey",
|
|
78
|
-
"dragon",
|
|
79
|
-
"master",
|
|
80
|
-
"hello",
|
|
81
|
-
"freedom",
|
|
82
|
-
"whatever",
|
|
83
|
-
"qazwsx",
|
|
84
|
-
"trustno1",
|
|
85
|
-
"jordan",
|
|
86
|
-
"harley",
|
|
87
|
-
"ranger",
|
|
88
|
-
"buster",
|
|
89
|
-
"thomas",
|
|
90
|
-
"tigger",
|
|
91
|
-
"robert",
|
|
92
|
-
"soccer",
|
|
93
|
-
"batman",
|
|
94
|
-
"test",
|
|
95
|
-
"pass",
|
|
96
|
-
"user",
|
|
97
|
-
"guest",
|
|
98
|
-
"login",
|
|
99
|
-
"secret",
|
|
100
|
-
"god",
|
|
101
|
-
"love",
|
|
102
|
-
"sex",
|
|
103
|
-
"money",
|
|
104
|
-
"password1",
|
|
105
|
-
"12345678",
|
|
106
|
-
"qwerty123",
|
|
107
|
-
"admin123",
|
|
108
|
-
"password!",
|
|
109
|
-
"password1!",
|
|
110
|
-
"password123",
|
|
111
|
-
"password123!"
|
|
112
|
-
];
|
|
113
|
-
const validatePassword = (password, options = {}) => {
|
|
114
|
-
const config = { ...DEFAULT_OPTIONS, ...options };
|
|
115
|
-
const errors = [];
|
|
116
|
-
const hints = [];
|
|
117
|
-
let score = 0;
|
|
118
|
-
if (password.length < config.minLength) {
|
|
119
|
-
errors.push(`Password must be at least ${config.minLength} characters long`);
|
|
120
|
-
hints.push(`Use at least ${config.minLength} characters`);
|
|
121
|
-
} else {
|
|
122
|
-
score += 20;
|
|
123
|
-
if (password.length < 12) {
|
|
124
|
-
hints.push("Use 12 or more characters for extra security");
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
if (config.requireUppercase && !/[A-Z]/.test(password)) {
|
|
128
|
-
errors.push("Password must contain at least one uppercase letter");
|
|
129
|
-
hints.push("Add an uppercase letter (A-Z)");
|
|
130
|
-
} else if (/[A-Z]/.test(password)) {
|
|
131
|
-
score += 15;
|
|
132
|
-
}
|
|
133
|
-
if (config.requireLowercase && !/[a-z]/.test(password)) {
|
|
134
|
-
errors.push("Password must contain at least one lowercase letter");
|
|
135
|
-
hints.push("Add a lowercase letter (a-z)");
|
|
136
|
-
} else if (/[a-z]/.test(password)) {
|
|
137
|
-
score += 15;
|
|
138
|
-
}
|
|
139
|
-
if (config.requireNumbers && !/\d/.test(password)) {
|
|
140
|
-
errors.push("Password must contain at least one number");
|
|
141
|
-
hints.push("Add a number (0-9)");
|
|
142
|
-
} else if (/\d/.test(password)) {
|
|
143
|
-
score += 15;
|
|
144
|
-
}
|
|
145
|
-
if (config.requireSpecialChars && !/[!@#$%^&*()_+\-=[\]{};':"\\|,.<>/?]/.test(password)) {
|
|
146
|
-
errors.push("Password must contain at least one special character");
|
|
147
|
-
hints.push("Add a special character (e.g. !@#$%)");
|
|
148
|
-
} else if (/[!@#$%^&*()_+\-=[\]{};':"\\|,.<>/?]/.test(password)) {
|
|
149
|
-
score += 15;
|
|
150
|
-
}
|
|
151
|
-
if (config.preventCommonPasswords && COMMON_PASSWORDS.includes(password.toLowerCase())) {
|
|
152
|
-
errors.push("Password is too common. Please choose a more unique password");
|
|
153
|
-
hints.push("Avoid common passwords or names");
|
|
154
|
-
}
|
|
155
|
-
if (password.length >= 12) {
|
|
156
|
-
score += 10;
|
|
157
|
-
} else if (password.length >= 10) {
|
|
158
|
-
score += 5;
|
|
159
|
-
}
|
|
160
|
-
const hasUppercase = /[A-Z]/.test(password);
|
|
161
|
-
const hasLowercase = /[a-z]/.test(password);
|
|
162
|
-
const hasNumbers = /\d/.test(password);
|
|
163
|
-
const hasSpecial = /[!@#$%^&*()_+\-=[\]{};':"\\|,.<>/?]/.test(password);
|
|
164
|
-
const complexityTypes = [hasUppercase, hasLowercase, hasNumbers, hasSpecial].filter(Boolean).length;
|
|
165
|
-
if (complexityTypes >= 4) {
|
|
166
|
-
score += 10;
|
|
167
|
-
} else if (complexityTypes >= 3) {
|
|
168
|
-
score += 5;
|
|
169
|
-
hints.push("Use a mix of uppercase, lowercase, numbers, and special characters");
|
|
170
|
-
}
|
|
171
|
-
let strength = "weak";
|
|
172
|
-
if (score >= 80) {
|
|
173
|
-
strength = "strong";
|
|
174
|
-
} else if (score >= 60) {
|
|
175
|
-
strength = "medium";
|
|
176
|
-
}
|
|
177
|
-
return {
|
|
178
|
-
isValid: errors.length === 0,
|
|
179
|
-
errors,
|
|
180
|
-
strength,
|
|
181
|
-
score: Math.min(score, 100),
|
|
182
|
-
hints: Array.from(new Set(hints))
|
|
183
|
-
// deduplicate
|
|
184
|
-
};
|
|
185
|
-
};
|
|
186
|
-
const getPasswordStrengthColor = (strength) => {
|
|
187
|
-
switch (strength) {
|
|
188
|
-
case "weak":
|
|
189
|
-
return "#dc3545";
|
|
190
|
-
case "medium":
|
|
191
|
-
return "#ffc107";
|
|
192
|
-
case "strong":
|
|
193
|
-
return "#28a745";
|
|
194
|
-
default:
|
|
195
|
-
return "#6c757d";
|
|
196
|
-
}
|
|
197
|
-
};
|
|
198
|
-
const getPasswordStrengthText = (strength) => {
|
|
199
|
-
switch (strength) {
|
|
200
|
-
case "weak":
|
|
201
|
-
return "Weak";
|
|
202
|
-
case "medium":
|
|
203
|
-
return "Medium";
|
|
204
|
-
case "strong":
|
|
205
|
-
return "Strong";
|
|
206
|
-
default:
|
|
207
|
-
return "Unknown";
|
|
208
|
-
}
|
|
209
|
-
};
|
|
210
|
-
|
|
211
|
-
const createUser = async (userData, options) => {
|
|
212
|
-
const db = await useDb(options);
|
|
213
|
-
const usersTable = options.tables.users;
|
|
214
|
-
const passwordOptions = getPasswordValidationOptions(options);
|
|
215
|
-
const passwordValidation = validatePassword(userData.password, passwordOptions);
|
|
216
|
-
if (!passwordValidation.isValid) {
|
|
217
|
-
throw new Error(`Password validation failed: ${passwordValidation.errors.join(", ")}`);
|
|
218
|
-
}
|
|
219
|
-
const hashedPassword = await bcrypt.hash(userData.password, 10);
|
|
220
|
-
const role = userData.role || "user";
|
|
221
|
-
await db.sql`
|
|
222
|
-
INSERT INTO {${usersTable}} (email, name, password, role, created_at, updated_at)
|
|
223
|
-
VALUES (${userData.email}, ${userData.name}, ${hashedPassword}, ${role}, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)
|
|
224
|
-
`;
|
|
225
|
-
const result = await db.sql`SELECT id, email, name, role, created_at, updated_at FROM {${usersTable}} WHERE email = ${userData.email}`;
|
|
226
|
-
if (result.rows.length === 0) {
|
|
227
|
-
throw new Error("Failed to retrieve created user.");
|
|
228
|
-
}
|
|
229
|
-
const user = result.rows[0];
|
|
230
|
-
return {
|
|
231
|
-
id: user.id,
|
|
232
|
-
email: user.email,
|
|
233
|
-
name: user.name,
|
|
234
|
-
role: user.role,
|
|
235
|
-
created_at: user.created_at instanceof Date ? user.created_at.toISOString() : user.created_at,
|
|
236
|
-
updated_at: user.updated_at instanceof Date ? user.updated_at.toISOString() : user.updated_at
|
|
237
|
-
};
|
|
238
|
-
};
|
|
239
|
-
const findUserByEmail = async (email, options) => {
|
|
240
|
-
const db = await useDb(options);
|
|
241
|
-
const usersTable = options.tables.users;
|
|
242
|
-
const result = await db.sql`SELECT * FROM {${usersTable}} WHERE email = ${email}`;
|
|
243
|
-
if (result.rows.length === 0) {
|
|
244
|
-
return null;
|
|
245
|
-
}
|
|
246
|
-
const user = result.rows[0];
|
|
247
|
-
return {
|
|
248
|
-
id: user.id,
|
|
249
|
-
email: user.email,
|
|
250
|
-
name: user.name,
|
|
251
|
-
password: user.password,
|
|
252
|
-
role: user.role,
|
|
253
|
-
created_at: user.created_at instanceof Date ? user.created_at.toISOString() : user.created_at,
|
|
254
|
-
updated_at: user.updated_at instanceof Date ? user.updated_at.toISOString() : user.updated_at
|
|
255
|
-
};
|
|
256
|
-
};
|
|
257
|
-
const updateUserPassword = async (email, newPassword, options) => {
|
|
258
|
-
const db = await useDb(options);
|
|
259
|
-
const usersTable = options.tables.users;
|
|
260
|
-
const passwordOptions = getPasswordValidationOptions(options);
|
|
261
|
-
const passwordValidation = validatePassword(newPassword, passwordOptions);
|
|
262
|
-
if (!passwordValidation.isValid) {
|
|
263
|
-
throw new Error(`Password validation failed: ${passwordValidation.errors.join(", ")}`);
|
|
264
|
-
}
|
|
265
|
-
const hashedPassword = await bcrypt.hash(newPassword, 10);
|
|
266
|
-
await db.sql`
|
|
267
|
-
UPDATE {${usersTable}}
|
|
268
|
-
SET password = ${hashedPassword}, updated_at = CURRENT_TIMESTAMP
|
|
269
|
-
WHERE email = ${email}
|
|
270
|
-
`;
|
|
271
|
-
};
|
|
272
|
-
const getCurrentUserFromToken = async (token, options) => {
|
|
273
|
-
const db = await useDb(options);
|
|
274
|
-
const personalAccessTokensTable = options.tables.personalAccessTokens;
|
|
275
|
-
const usersTable = options.tables.users;
|
|
276
|
-
const tokenResult = await db.sql`
|
|
277
|
-
SELECT tokenable_id FROM {${personalAccessTokensTable}}
|
|
278
|
-
WHERE token = ${token}
|
|
279
|
-
`;
|
|
280
|
-
if (tokenResult.rows.length === 0) {
|
|
281
|
-
return null;
|
|
282
|
-
}
|
|
283
|
-
const userId = tokenResult.rows[0].tokenable_id;
|
|
284
|
-
const userResult = await db.sql`
|
|
285
|
-
SELECT * FROM {${usersTable}}
|
|
286
|
-
WHERE id = ${userId}
|
|
287
|
-
`;
|
|
288
|
-
if (userResult.rows.length === 0) {
|
|
289
|
-
return null;
|
|
290
|
-
}
|
|
291
|
-
return userResult.rows[0];
|
|
292
|
-
};
|
|
293
|
-
|
|
294
|
-
const createUsersTable = async (options) => {
|
|
295
|
-
const connectorName = options.connector.name;
|
|
296
|
-
const db = await useDb(options);
|
|
297
|
-
const tableName = options.tables.users;
|
|
298
|
-
console.log(`[Nuxt Users] DB:Create ${connectorName} Users Table Creating ${tableName}...`);
|
|
299
|
-
if (connectorName === "sqlite") {
|
|
300
|
-
await db.sql`
|
|
301
|
-
CREATE TABLE IF NOT EXISTS {${tableName}} (
|
|
302
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
303
|
-
email TEXT NOT NULL UNIQUE,
|
|
304
|
-
name TEXT NOT NULL,
|
|
305
|
-
password TEXT NOT NULL,
|
|
306
|
-
role TEXT NOT NULL DEFAULT 'user',
|
|
307
|
-
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
308
|
-
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
309
|
-
)
|
|
310
|
-
`;
|
|
311
|
-
}
|
|
312
|
-
if (connectorName === "mysql") {
|
|
313
|
-
await db.sql`
|
|
314
|
-
CREATE TABLE IF NOT EXISTS {${tableName}} (
|
|
315
|
-
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
316
|
-
email VARCHAR(255) NOT NULL UNIQUE,
|
|
317
|
-
name VARCHAR(255) NOT NULL,
|
|
318
|
-
password VARCHAR(255) NOT NULL,
|
|
319
|
-
role VARCHAR(32) NOT NULL DEFAULT 'user',
|
|
320
|
-
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
321
|
-
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
322
|
-
)
|
|
323
|
-
`;
|
|
324
|
-
}
|
|
325
|
-
if (connectorName === "postgresql") {
|
|
326
|
-
await db.sql`
|
|
327
|
-
CREATE TABLE IF NOT EXISTS {${tableName}} (
|
|
328
|
-
id SERIAL PRIMARY KEY,
|
|
329
|
-
email VARCHAR(255) NOT NULL UNIQUE,
|
|
330
|
-
name VARCHAR(255) NOT NULL,
|
|
331
|
-
password VARCHAR(255) NOT NULL,
|
|
332
|
-
role VARCHAR(32) NOT NULL DEFAULT 'user',
|
|
333
|
-
created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
|
|
334
|
-
updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP
|
|
335
|
-
)
|
|
336
|
-
`;
|
|
337
|
-
}
|
|
338
|
-
console.log(`[Nuxt Users] DB:Create ${connectorName} Users Table Fields: id, email, name, password, role, created_at, updated_at \u2705`);
|
|
339
|
-
};
|
|
340
|
-
|
|
341
|
-
const createPersonalAccessTokensTable = async (options) => {
|
|
342
|
-
const connectorName = options.connector.name;
|
|
343
|
-
const db = await useDb(options);
|
|
344
|
-
const tableName = options.tables.personalAccessTokens;
|
|
345
|
-
console.log(`[Nuxt Users] DB:Create Personal Access Tokens ${connectorName} Table Creating ${tableName} table with ${connectorName} connector...`);
|
|
346
|
-
if (connectorName === "sqlite") {
|
|
347
|
-
await db.sql`
|
|
348
|
-
CREATE TABLE IF NOT EXISTS {${tableName}} (
|
|
349
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
350
|
-
tokenable_type TEXT NOT NULL,
|
|
351
|
-
tokenable_id INTEGER NOT NULL,
|
|
352
|
-
name TEXT NOT NULL,
|
|
353
|
-
token TEXT NOT NULL UNIQUE,
|
|
354
|
-
abilities TEXT,
|
|
355
|
-
last_used_at DATETIME,
|
|
356
|
-
expires_at DATETIME,
|
|
357
|
-
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
358
|
-
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
359
|
-
)
|
|
360
|
-
`;
|
|
361
|
-
}
|
|
362
|
-
if (connectorName === "mysql") {
|
|
363
|
-
await db.sql`
|
|
364
|
-
CREATE TABLE IF NOT EXISTS {${tableName}} (
|
|
365
|
-
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
366
|
-
tokenable_type VARCHAR(255) NOT NULL,
|
|
367
|
-
tokenable_id INT NOT NULL,
|
|
368
|
-
name VARCHAR(255) NOT NULL,
|
|
369
|
-
token VARCHAR(255) NOT NULL UNIQUE,
|
|
370
|
-
abilities TEXT,
|
|
371
|
-
last_used_at DATETIME,
|
|
372
|
-
expires_at DATETIME,
|
|
373
|
-
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
374
|
-
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
|
375
|
-
)
|
|
376
|
-
`;
|
|
377
|
-
}
|
|
378
|
-
if (connectorName === "postgresql") {
|
|
379
|
-
await db.sql`
|
|
380
|
-
CREATE TABLE IF NOT EXISTS {${tableName}} (
|
|
381
|
-
id SERIAL PRIMARY KEY,
|
|
382
|
-
tokenable_type VARCHAR(255) NOT NULL,
|
|
383
|
-
tokenable_id INT NOT NULL,
|
|
384
|
-
name VARCHAR(255) NOT NULL,
|
|
385
|
-
token VARCHAR(255) NOT NULL UNIQUE,
|
|
386
|
-
abilities TEXT,
|
|
387
|
-
last_used_at TIMESTAMPTZ,
|
|
388
|
-
expires_at TIMESTAMPTZ,
|
|
389
|
-
created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
|
|
390
|
-
updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP
|
|
391
|
-
)
|
|
392
|
-
`;
|
|
393
|
-
}
|
|
394
|
-
console.log(`[Nuxt Users] DB:Create Personal Access Tokens ${connectorName} Table Fields: id, tokenable_type, tokenable_id, name, token, abilities, last_used_at, expires_at, created_at, updated_at \u2705`);
|
|
395
|
-
};
|
|
396
|
-
|
|
397
|
-
const createPasswordResetTokensTable = async (options) => {
|
|
398
|
-
const connectorName = options.connector.name;
|
|
399
|
-
const db = await useDb(options);
|
|
400
|
-
const tableName = options.tables.passwordResetTokens;
|
|
401
|
-
console.log(`[Nuxt Users] DB:Create Password Reset Tokens ${connectorName} Table Creating ${tableName} table with ${connectorName} connector...`);
|
|
402
|
-
if (connectorName === "sqlite") {
|
|
403
|
-
await db.sql`
|
|
404
|
-
CREATE TABLE IF NOT EXISTS {${tableName}} (
|
|
405
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
406
|
-
email TEXT NOT NULL,
|
|
407
|
-
token TEXT NOT NULL UNIQUE,
|
|
408
|
-
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
409
|
-
)
|
|
410
|
-
`;
|
|
411
|
-
}
|
|
412
|
-
if (connectorName === "mysql") {
|
|
413
|
-
await db.sql`
|
|
414
|
-
CREATE TABLE IF NOT EXISTS {${tableName}} (
|
|
415
|
-
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
416
|
-
email VARCHAR(255) NOT NULL,
|
|
417
|
-
token VARCHAR(255) NOT NULL UNIQUE,
|
|
418
|
-
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
419
|
-
)
|
|
420
|
-
`;
|
|
421
|
-
}
|
|
422
|
-
if (connectorName === "postgresql") {
|
|
423
|
-
await db.sql`
|
|
424
|
-
CREATE TABLE IF NOT EXISTS {${tableName}} (
|
|
425
|
-
id SERIAL PRIMARY KEY,
|
|
426
|
-
email VARCHAR(255) NOT NULL,
|
|
427
|
-
token VARCHAR(255) NOT NULL UNIQUE,
|
|
428
|
-
created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP
|
|
429
|
-
)
|
|
430
|
-
`;
|
|
431
|
-
}
|
|
432
|
-
await db.sql`CREATE INDEX IF NOT EXISTS idx_password_reset_tokens_email ON {${tableName}} (email)`;
|
|
433
|
-
await db.sql`CREATE INDEX IF NOT EXISTS idx_password_reset_tokens_token ON {${tableName}} (token)`;
|
|
434
|
-
console.log(`[Nuxt Users] DB:Create Password Reset Tokens ${connectorName} Table Fields: id, email, token, created_at \u2705`);
|
|
435
|
-
};
|
|
436
|
-
|
|
437
|
-
const createMigrationsTable = async (options) => {
|
|
438
|
-
const connectorName = options.connector.name;
|
|
439
|
-
const db = await useDb(options);
|
|
440
|
-
const tableName = "migrations";
|
|
441
|
-
console.log(`[Nuxt Users] DB:Create Migrations ${connectorName} Table Creating ${tableName} table with ${connectorName} connector...`);
|
|
442
|
-
if (connectorName === "sqlite") {
|
|
443
|
-
await db.sql`
|
|
444
|
-
CREATE TABLE IF NOT EXISTS {${tableName}} (
|
|
445
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
446
|
-
name TEXT NOT NULL UNIQUE,
|
|
447
|
-
executed_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
448
|
-
)
|
|
449
|
-
`;
|
|
450
|
-
}
|
|
451
|
-
if (connectorName === "mysql") {
|
|
452
|
-
await db.sql`
|
|
453
|
-
CREATE TABLE IF NOT EXISTS {${tableName}} (
|
|
454
|
-
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
455
|
-
name VARCHAR(255) NOT NULL UNIQUE,
|
|
456
|
-
executed_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
457
|
-
)
|
|
458
|
-
`;
|
|
459
|
-
}
|
|
460
|
-
if (connectorName === "postgresql") {
|
|
461
|
-
await db.sql`
|
|
462
|
-
CREATE TABLE IF NOT EXISTS {${tableName}} (
|
|
463
|
-
id SERIAL PRIMARY KEY,
|
|
464
|
-
name VARCHAR(255) NOT NULL UNIQUE,
|
|
465
|
-
executed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
466
|
-
)
|
|
467
|
-
`;
|
|
468
|
-
}
|
|
469
|
-
console.log(`[Nuxt Users] DB:Create Migrations ${connectorName} Table successfull \u2705`);
|
|
470
|
-
};
|
|
471
|
-
|
|
472
|
-
const migrations = [
|
|
473
|
-
{
|
|
474
|
-
name: "create_migrations_table",
|
|
475
|
-
run: createMigrationsTable
|
|
476
|
-
},
|
|
477
|
-
{
|
|
478
|
-
name: "create_users_table",
|
|
479
|
-
run: createUsersTable
|
|
480
|
-
},
|
|
481
|
-
{
|
|
482
|
-
name: "create_personal_access_tokens_table",
|
|
483
|
-
run: createPersonalAccessTokensTable
|
|
484
|
-
},
|
|
485
|
-
{
|
|
486
|
-
name: "create_password_reset_tokens_table",
|
|
487
|
-
run: createPasswordResetTokensTable
|
|
488
|
-
}
|
|
489
|
-
];
|
|
490
|
-
const getAppliedMigrations = async (options) => {
|
|
491
|
-
const db = await useDb(options);
|
|
492
|
-
try {
|
|
493
|
-
const result = await db.sql`SELECT name FROM migrations ORDER BY id`;
|
|
494
|
-
return result.rows.map((row) => row.name);
|
|
495
|
-
} catch {
|
|
496
|
-
return [];
|
|
497
|
-
}
|
|
498
|
-
};
|
|
499
|
-
const markMigrationAsApplied = async (options, migrationName) => {
|
|
500
|
-
const db = await useDb(options);
|
|
501
|
-
await db.sql`INSERT INTO migrations (name) VALUES (${migrationName})`;
|
|
502
|
-
};
|
|
503
|
-
const runMigrations = async (options) => {
|
|
504
|
-
console.log("[Nuxt Users] Starting migration system...");
|
|
505
|
-
await createMigrationsTable(options);
|
|
506
|
-
const appliedMigrations = await getAppliedMigrations(options);
|
|
507
|
-
console.log(`[Nuxt Users] Applied migrations: ${appliedMigrations.join(", ")}`);
|
|
508
|
-
const pendingMigrations = migrations.filter((migration) => !appliedMigrations.includes(migration.name));
|
|
509
|
-
if (pendingMigrations.length === 0) {
|
|
510
|
-
console.log("[Nuxt Users] No pending migrations to run.");
|
|
511
|
-
return;
|
|
512
|
-
}
|
|
513
|
-
console.log(`[Nuxt Users] Found ${pendingMigrations.length} pending migrations:`);
|
|
514
|
-
pendingMigrations.forEach((migration) => {
|
|
515
|
-
console.log(`[Nuxt Users] - ${migration.name}`);
|
|
516
|
-
});
|
|
517
|
-
for (const migration of pendingMigrations) {
|
|
518
|
-
console.log(`[Nuxt Users] Running migration: ${migration.name}`);
|
|
519
|
-
try {
|
|
520
|
-
await migration.run(options);
|
|
521
|
-
await markMigrationAsApplied(options, migration.name);
|
|
522
|
-
console.log(`[Nuxt Users] \u2713 Migration ${migration.name} successfull \u2705`);
|
|
523
|
-
} catch (error) {
|
|
524
|
-
console.error(`[Nuxt Users] \u2717 Migration ${migration.name} failed:`, error);
|
|
525
|
-
throw error;
|
|
526
|
-
}
|
|
527
|
-
}
|
|
528
|
-
console.log("[Nuxt Users] All migrations successfull \u2705");
|
|
529
|
-
};
|
|
530
|
-
|
|
531
|
-
export { createUser as a, updateUserPassword as b, checkTableExists as c, createUsersTable as d, createPersonalAccessTokensTable as e, findUserByEmail as f, getCurrentUserFromToken as g, createPasswordResetTokensTable as h, createMigrationsTable as i, getPasswordValidationOptions as j, getPasswordStrengthColor as k, getPasswordStrengthText as l, runMigrations as r, useDb as u, validatePassword as v };
|