nuxt-users 1.1.6 → 1.3.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 +47 -0
- package/README.md +5 -2
- package/dist/cli.mjs +30 -24
- package/dist/module.d.mts +1 -1
- package/dist/module.d.ts +1 -1
- package/dist/module.json +1 -1
- package/dist/module.mjs +21 -5
- package/dist/runtime/assets/colors.css +1 -1
- package/dist/runtime/components/ForgotPasswordForm.vue +1 -1
- package/dist/runtime/components/LoginForm.vue +6 -4
- package/dist/runtime/components/LogoutLink.vue +62 -0
- package/dist/runtime/components/LogoutLink.vue.d.ts +20 -0
- package/dist/runtime/components/ResetPasswordForm.vue +1 -1
- package/dist/runtime/composables/useAuth.d.ts +5 -0
- package/dist/runtime/composables/useAuth.js +19 -0
- package/dist/runtime/middleware/auth.global.d.ts +2 -0
- package/dist/runtime/middleware/auth.global.js +12 -0
- package/dist/runtime/plugin.js +0 -1
- package/dist/runtime/server/api/auth/forgot-password.post.js +2 -2
- package/dist/runtime/server/api/auth/reset-password.post.js +2 -2
- package/dist/runtime/server/api/login.post.d.ts +1 -0
- package/dist/runtime/server/api/login.post.js +1 -1
- package/dist/runtime/server/api/logout.get.d.ts +4 -0
- package/dist/runtime/server/api/logout.get.js +21 -0
- package/dist/runtime/server/services/password.js +9 -9
- package/dist/shared/{nuxt-users.Dtq4WcpY.d.mts → nuxt-users.DGRKT2Tq.d.mts} +9 -1
- package/dist/shared/{nuxt-users.Dtq4WcpY.d.ts → nuxt-users.DGRKT2Tq.d.ts} +9 -1
- package/dist/shared/{nuxt-users.eSQUrS6l.mjs → nuxt-users.DZkU2AbH.mjs} +19 -13
- package/dist/utils.d.mts +2 -1
- package/dist/utils.d.ts +2 -1
- package/dist/utils.mjs +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,53 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
3
|
|
|
4
|
+
## v1.3.0
|
|
5
|
+
|
|
6
|
+
[compare changes](https://github.com/rrd108/nuxt-users/compare/v1.2.0...v1.3.0)
|
|
7
|
+
|
|
8
|
+
### 🚀 Enhancements
|
|
9
|
+
|
|
10
|
+
- Adds theme support with light/dark mode ([005ea87](https://github.com/rrd108/nuxt-users/commit/005ea87))
|
|
11
|
+
- Adds logout functionality ([a61b4e8](https://github.com/rrd108/nuxt-users/commit/a61b4e8))
|
|
12
|
+
|
|
13
|
+
### 💅 Refactors
|
|
14
|
+
|
|
15
|
+
- Restyles login form for better UX closes #51 ([#51](https://github.com/rrd108/nuxt-users/issues/51))
|
|
16
|
+
|
|
17
|
+
### 🏡 Chore
|
|
18
|
+
|
|
19
|
+
- **release:** V1.2.0 ([54fd5c8](https://github.com/rrd108/nuxt-users/commit/54fd5c8))
|
|
20
|
+
|
|
21
|
+
### ❤️ Contributors
|
|
22
|
+
|
|
23
|
+
- Rrd108 ([@rrd108](https://github.com/rrd108))
|
|
24
|
+
|
|
25
|
+
## v1.2.0
|
|
26
|
+
|
|
27
|
+
[compare changes](https://github.com/rrd108/nuxt-users/compare/v1.1.6...v1.2.0)
|
|
28
|
+
|
|
29
|
+
### 🚀 Enhancements
|
|
30
|
+
|
|
31
|
+
- Adds user role functionality closes #25 ([#25](https://github.com/rrd108/nuxt-users/issues/25))
|
|
32
|
+
- Adds authentication middleware and route whitelisting closes #52 ([#52](https://github.com/rrd108/nuxt-users/issues/52))
|
|
33
|
+
|
|
34
|
+
### 🩹 Fixes
|
|
35
|
+
|
|
36
|
+
- **ci:** Adds playground preparation step to CI ([cf9af1f](https://github.com/rrd108/nuxt-users/commit/cf9af1f))
|
|
37
|
+
|
|
38
|
+
### 💅 Refactors
|
|
39
|
+
|
|
40
|
+
- Uses default table names as fallback ([dcee2ee](https://github.com/rrd108/nuxt-users/commit/dcee2ee))
|
|
41
|
+
|
|
42
|
+
### 🏡 Chore
|
|
43
|
+
|
|
44
|
+
- **release:** V1.1.6 ([1222bcd](https://github.com/rrd108/nuxt-users/commit/1222bcd))
|
|
45
|
+
- Consistently prefixes logs with "[Nuxt Users]" ([9ed1df1](https://github.com/rrd108/nuxt-users/commit/9ed1df1))
|
|
46
|
+
|
|
47
|
+
### ❤️ Contributors
|
|
48
|
+
|
|
49
|
+
- Rrd108 ([@rrd108](https://github.com/rrd108))
|
|
50
|
+
|
|
4
51
|
## v1.1.6
|
|
5
52
|
|
|
6
53
|
[compare changes](https://github.com/rrd108/nuxt-users/compare/v1.1.5...v1.1.6)
|
package/README.md
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
# Nuxt Users
|
|
2
2
|
|
|
3
|
-
A user authentication module for Nuxt 3 with database support for SQLite and
|
|
3
|
+
A user authentication module for Nuxt 3 and Nuxt 4 with database support for SQLite, MySQL, and PostgreSQL.
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
7
|
- 🔐 User authentication with bcrypt password hashing
|
|
8
|
-
- 🗄️ Database support (SQLite, MySQL)
|
|
8
|
+
- 🗄️ Database support (SQLite, MySQL, PostgreSQL)
|
|
9
9
|
- 🛠️ CLI commands for database management
|
|
10
10
|
- 🔑 Password Reset Functionality
|
|
11
11
|
- 📦 Zero-config setup with sensible defaults
|
|
12
12
|
- 🔧 TypeScript support
|
|
13
|
+
- 🚀 Nuxt 3 & 4 compatibility
|
|
13
14
|
|
|
14
15
|
## Quick Start
|
|
15
16
|
|
|
@@ -35,6 +36,8 @@ npx nuxt-users migrate
|
|
|
35
36
|
|
|
36
37
|
# Create your first user
|
|
37
38
|
npx nuxt-users create-user user@example.com "John Doe" password123
|
|
39
|
+
# Create an admin user
|
|
40
|
+
npx nuxt-users create-user admin@example.com "Admin User" adminpass123 admin
|
|
38
41
|
```
|
|
39
42
|
|
|
40
43
|
## Documentation
|
package/dist/cli.mjs
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { defineCommand, runMain } from 'citty';
|
|
3
3
|
import 'db0';
|
|
4
4
|
import 'bcrypt';
|
|
5
|
-
import { r as runMigrations, a as createUser$1, d as createUsersTable$1, e as createPersonalAccessTokensTable$1, g as createPasswordResetTokensTable$1, h as createMigrationsTable$1 } from './shared/nuxt-users.
|
|
5
|
+
import { r as runMigrations, a as createUser$1, d as createUsersTable$1, e as createPersonalAccessTokensTable$1, g as createPasswordResetTokensTable$1, h as createMigrationsTable$1 } from './shared/nuxt-users.DZkU2AbH.mjs';
|
|
6
6
|
import { loadNuxt } from '@nuxt/kit';
|
|
7
7
|
|
|
8
8
|
const defaultOptions = {
|
|
@@ -85,7 +85,7 @@ const loadOptions = async () => {
|
|
|
85
85
|
}
|
|
86
86
|
} catch (error) {
|
|
87
87
|
console.log("[Nuxt Users] Could not load Nuxt project, using environment variables");
|
|
88
|
-
console.error(error);
|
|
88
|
+
console.error("[Nuxt Users] Error:", error);
|
|
89
89
|
return getOptionsFromEnv();
|
|
90
90
|
}
|
|
91
91
|
};
|
|
@@ -132,17 +132,23 @@ const createUser = defineCommand({
|
|
|
132
132
|
type: "string",
|
|
133
133
|
description: "User password",
|
|
134
134
|
required: true
|
|
135
|
+
},
|
|
136
|
+
role: {
|
|
137
|
+
alias: "r",
|
|
138
|
+
type: "string",
|
|
139
|
+
description: 'User role (defaults to "user")',
|
|
140
|
+
default: "user"
|
|
135
141
|
}
|
|
136
142
|
},
|
|
137
143
|
async run({ args }) {
|
|
138
|
-
const { email, name, password } = args;
|
|
144
|
+
const { email, name, password, role } = args;
|
|
139
145
|
const options = await loadOptions();
|
|
140
146
|
try {
|
|
141
|
-
const user = await createUser$1({ email, name, password }, options);
|
|
142
|
-
console.log(`[
|
|
147
|
+
const user = await createUser$1({ email, name, password, role }, options);
|
|
148
|
+
console.log(`[Nuxt Users] User created successfully: ${user.email} (role: ${user.role})`);
|
|
143
149
|
process.exit(0);
|
|
144
150
|
} catch (error) {
|
|
145
|
-
console.error("[
|
|
151
|
+
console.error("[Nuxt Users] Error:", error);
|
|
146
152
|
process.exit(1);
|
|
147
153
|
}
|
|
148
154
|
}
|
|
@@ -160,7 +166,7 @@ const createUsersTable = defineCommand({
|
|
|
160
166
|
await createUsersTable$1(options);
|
|
161
167
|
console.log("[Nuxt Users] Users table created successfully!");
|
|
162
168
|
} catch (error) {
|
|
163
|
-
console.error("[DB:Create Users Table
|
|
169
|
+
console.error("[Nuxt Users] DB:Create Users Table Error:", error);
|
|
164
170
|
process.exit(1);
|
|
165
171
|
}
|
|
166
172
|
}
|
|
@@ -178,7 +184,7 @@ const createPersonalAccessTokensTable = defineCommand({
|
|
|
178
184
|
await createPersonalAccessTokensTable$1(options);
|
|
179
185
|
console.log("[Nuxt Users] Personal access tokens table created successfully!");
|
|
180
186
|
} catch (error) {
|
|
181
|
-
console.error("[DB:Create Personal Access Tokens Table
|
|
187
|
+
console.error("[Nuxt Users] DB:Create Personal Access Tokens Table Error:", error);
|
|
182
188
|
process.exit(1);
|
|
183
189
|
}
|
|
184
190
|
}
|
|
@@ -196,7 +202,7 @@ const createPasswordResetTokensTable = defineCommand({
|
|
|
196
202
|
await createPasswordResetTokensTable$1(options);
|
|
197
203
|
console.log("[Nuxt Users] Password reset tokens table created successfully!");
|
|
198
204
|
} catch (error) {
|
|
199
|
-
console.error("[DB:Create Password Reset Tokens Table
|
|
205
|
+
console.error("[Nuxt Users] DB:Create Password Reset Tokens Table Error:", error);
|
|
200
206
|
process.exit(1);
|
|
201
207
|
}
|
|
202
208
|
}
|
|
@@ -214,7 +220,7 @@ const createMigrationsTable = defineCommand({
|
|
|
214
220
|
await createMigrationsTable$1(options);
|
|
215
221
|
console.log("[Nuxt Users] Migrations table created successfully!");
|
|
216
222
|
} catch (error) {
|
|
217
|
-
console.error("[DB:Create Migrations Table
|
|
223
|
+
console.error("[Nuxt Users] DB:Create Migrations Table Error:", error);
|
|
218
224
|
process.exit(1);
|
|
219
225
|
}
|
|
220
226
|
}
|
|
@@ -229,28 +235,28 @@ const projectInfo = defineCommand({
|
|
|
229
235
|
try {
|
|
230
236
|
console.log("[Nuxt Users] Loading Nuxt project...");
|
|
231
237
|
const nuxt = await loadNuxt({ cwd: process.cwd() });
|
|
232
|
-
console.log("\u2705 Nuxt project loaded successfully!");
|
|
233
|
-
console.log("\u{1F4C1} Source directory:", nuxt.options.srcDir);
|
|
234
|
-
console.log("\u{1F310} Base URL:", nuxt.options.app?.baseURL || "/");
|
|
238
|
+
console.log("[Nuxt Users] \u2705 Nuxt project loaded successfully!");
|
|
239
|
+
console.log("[Nuxt Users] \u{1F4C1} Source directory:", nuxt.options.srcDir);
|
|
240
|
+
console.log("[Nuxt Users] \u{1F310} Base URL:", nuxt.options.app?.baseURL || "/");
|
|
235
241
|
const nuxtUsersConfig = nuxt.options.runtimeConfig?.nuxtUsers;
|
|
236
242
|
if (nuxtUsersConfig) {
|
|
237
|
-
console.log("\u{1F527} Nuxt Users module configuration:");
|
|
238
|
-
console.log("
|
|
239
|
-
console.log("
|
|
240
|
-
console.log("
|
|
241
|
-
console.log("
|
|
243
|
+
console.log("[Nuxt Users] \u{1F527} Nuxt Users module configuration:");
|
|
244
|
+
console.log("[Nuxt Users] Database connector:", nuxtUsersConfig.connector?.name);
|
|
245
|
+
console.log("[Nuxt Users] Users table:", nuxtUsersConfig.tables?.users);
|
|
246
|
+
console.log("[Nuxt Users] Personal access tokens table:", nuxtUsersConfig.tables?.personalAccessTokens);
|
|
247
|
+
console.log("[Nuxt Users] Password reset tokens table:", nuxtUsersConfig.tables?.passwordResetTokens);
|
|
242
248
|
} else {
|
|
243
|
-
console.log("\u26A0\uFE0F Nuxt Users module not configured in runtime config");
|
|
249
|
+
console.log("[Nuxt Users] \u26A0\uFE0F Nuxt Users module not configured in runtime config");
|
|
244
250
|
}
|
|
245
251
|
const publicConfig = nuxt.options.runtimeConfig?.public?.nuxtUsers;
|
|
246
252
|
if (publicConfig) {
|
|
247
|
-
console.log("\u{1F30D} Public runtime config:");
|
|
248
|
-
console.log("
|
|
249
|
-
console.log("
|
|
250
|
-
console.log("
|
|
253
|
+
console.log("[Nuxt Users] \u{1F30D} Public runtime config:");
|
|
254
|
+
console.log("[Nuxt Users] Users table exists:", publicConfig.tables?.users);
|
|
255
|
+
console.log("[Nuxt Users] Personal access tokens table exists:", publicConfig.tables?.personalAccessTokens);
|
|
256
|
+
console.log("[Nuxt Users] Password reset tokens table exists:", publicConfig.tables?.passwordResetTokens);
|
|
251
257
|
}
|
|
252
258
|
} catch (error) {
|
|
253
|
-
console.error("\u274C Could not load Nuxt project:", error);
|
|
259
|
+
console.error("[Nuxt Users] \u274C Could not load Nuxt project:", error);
|
|
254
260
|
process.exit(1);
|
|
255
261
|
}
|
|
256
262
|
}
|
package/dist/module.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as _nuxt_schema from '@nuxt/schema';
|
|
2
|
-
import { M as ModuleOptions } from './shared/nuxt-users.
|
|
2
|
+
import { M as ModuleOptions } from './shared/nuxt-users.DGRKT2Tq.mjs';
|
|
3
3
|
|
|
4
4
|
declare const defaultOptions: ModuleOptions;
|
|
5
5
|
declare const _default: _nuxt_schema.NuxtModule<ModuleOptions, ModuleOptions, false>;
|
package/dist/module.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as _nuxt_schema from '@nuxt/schema';
|
|
2
|
-
import { M as ModuleOptions } from './shared/nuxt-users.
|
|
2
|
+
import { M as ModuleOptions } from './shared/nuxt-users.DGRKT2Tq.js';
|
|
3
3
|
|
|
4
4
|
declare const defaultOptions: ModuleOptions;
|
|
5
5
|
declare const _default: _nuxt_schema.NuxtModule<ModuleOptions, ModuleOptions, false>;
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { defineNuxtModule, createResolver, addPlugin, addServerHandler, addComponent } from '@nuxt/kit';
|
|
1
|
+
import { defineNuxtModule, createResolver, addPlugin, addImportsDir, addServerHandler, addComponent } from '@nuxt/kit';
|
|
2
2
|
import { defu } from 'defu';
|
|
3
3
|
|
|
4
4
|
const defaultOptions = {
|
|
@@ -28,6 +28,9 @@ const defaultOptions = {
|
|
|
28
28
|
defaults: {
|
|
29
29
|
from: '"Nuxt Users Module" <noreply@example.com>'
|
|
30
30
|
}
|
|
31
|
+
},
|
|
32
|
+
auth: {
|
|
33
|
+
whitelist: ["/login"]
|
|
31
34
|
}
|
|
32
35
|
};
|
|
33
36
|
const module = defineNuxtModule({
|
|
@@ -43,16 +46,20 @@ const module = defineNuxtModule({
|
|
|
43
46
|
nuxt.options.runtimeConfig.nuxtUsers = {
|
|
44
47
|
...runtimeConfigOptions,
|
|
45
48
|
tables: {
|
|
46
|
-
migrations: options.tables?.migrations ||
|
|
47
|
-
users: options.tables?.users ||
|
|
48
|
-
personalAccessTokens: options.tables?.personalAccessTokens ||
|
|
49
|
-
passwordResetTokens: options.tables?.passwordResetTokens ||
|
|
49
|
+
migrations: options.tables?.migrations || defaultOptions.tables.migrations,
|
|
50
|
+
users: options.tables?.users || defaultOptions.tables.users,
|
|
51
|
+
personalAccessTokens: options.tables?.personalAccessTokens || defaultOptions.tables.personalAccessTokens,
|
|
52
|
+
passwordResetTokens: options.tables?.passwordResetTokens || defaultOptions.tables.passwordResetTokens
|
|
53
|
+
},
|
|
54
|
+
auth: {
|
|
55
|
+
whitelist: options.auth?.whitelist || defaultOptions.auth?.whitelist || ["/login"]
|
|
50
56
|
}
|
|
51
57
|
};
|
|
52
58
|
addPlugin({
|
|
53
59
|
src: resolver.resolve("./runtime/plugin"),
|
|
54
60
|
mode: "server"
|
|
55
61
|
});
|
|
62
|
+
addImportsDir(resolver.resolve("./runtime/composables"));
|
|
56
63
|
addServerHandler({
|
|
57
64
|
route: "/api/login",
|
|
58
65
|
method: "post",
|
|
@@ -68,6 +75,11 @@ const module = defineNuxtModule({
|
|
|
68
75
|
method: "post",
|
|
69
76
|
handler: resolver.resolve("./runtime/server/api/auth/reset-password.post")
|
|
70
77
|
});
|
|
78
|
+
addServerHandler({
|
|
79
|
+
route: "/api/logout",
|
|
80
|
+
method: "get",
|
|
81
|
+
handler: resolver.resolve("./runtime/server/api/logout.get")
|
|
82
|
+
});
|
|
71
83
|
addComponent({
|
|
72
84
|
name: "LoginForm",
|
|
73
85
|
filePath: resolver.resolve("./runtime/components/LoginForm.vue")
|
|
@@ -80,6 +92,10 @@ const module = defineNuxtModule({
|
|
|
80
92
|
name: "ResetPasswordForm",
|
|
81
93
|
filePath: resolver.resolve("./runtime/components/ResetPasswordForm.vue")
|
|
82
94
|
});
|
|
95
|
+
addComponent({
|
|
96
|
+
name: "LogoutLink",
|
|
97
|
+
filePath: resolver.resolve("./runtime/components/LogoutLink.vue")
|
|
98
|
+
});
|
|
83
99
|
nuxt.options.css = nuxt.options.css || [];
|
|
84
100
|
nuxt.options.css.push(resolver.resolve("./runtime/assets/colors.css"));
|
|
85
101
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
:root{--color-primary:#3b82f6;--color-primary-dark:#2563eb;--color-primary-light:#60a5fa;--color-secondary:#059669;--color-secondary-dark:#047857;--color-secondary-light:#10b981;--color-white:#fff;--color-black:#000;--color-gray-50:#f9fafb;--color-gray-100:#f3f4f6;--color-gray-200:#e5e7eb;--color-gray-300:#d1d5db;--color-gray-400:#9ca3af;--color-gray-500:#6b7280;--color-gray-600:#4b5563;--color-gray-700:#374151;--color-gray-800:#1f2937;--color-gray-900:#111827;--color-success:#059669;--color-success-light:#f0fdf4;--color-warning:#f59e0b;--color-warning-light:#fef3c7;--color-warning-text:#92400e;--color-error:#dc2626;--color-error-light:#fef2f2;--color-error-border:#fecaca;--color-error-alt:#db5050;--color-border:#e5e7eb;--color-border-light:#d1d5db;--color-border-dark:#ccc;--color-bg-primary:#fff;--color-bg-secondary:#f9fafb;--color-bg-tertiary:#f3f4f6}
|
|
1
|
+
:root{--color-primary:#60a5fa;--color-primary-dark:#3b82f6;--color-primary-light:#93c5fd;--color-secondary:#10b981;--color-secondary-dark:#059669;--color-secondary-light:#34d399;--color-white:#000;--color-black:#fff;--color-gray-50:#111827;--color-gray-100:#1f2937;--color-gray-200:#374151;--color-gray-300:#4b5563;--color-gray-400:#6b7280;--color-gray-500:#9ca3af;--color-gray-600:#d1d5db;--color-gray-700:#e5e7eb;--color-gray-800:#f3f4f6;--color-gray-900:#f9fafb;--color-success:#10b981;--color-success-light:#064e3b;--color-warning:#fbbf24;--color-warning-light:#451a03;--color-warning-text:#fef3c7;--color-error:#ef4444;--color-error-light:#450a0a;--color-error-border:#7f1d1d;--color-error-alt:#f87171;--color-border:#374151;--color-border-light:#4b5563;--color-border-dark:#6b7280;--color-bg-primary:#111827;--color-bg-secondary:#1f2937;--color-bg-tertiary:#374151}@media (prefers-color-scheme:light){.light,:root{--color-primary:#3b82f6;--color-primary-dark:#2563eb;--color-primary-light:#60a5fa;--color-secondary:#059669;--color-secondary-dark:#047857;--color-secondary-light:#10b981;--color-white:#fff;--color-black:#000;--color-gray-50:#f9fafb;--color-gray-100:#f3f4f6;--color-gray-200:#e5e7eb;--color-gray-300:#d1d5db;--color-gray-400:#9ca3af;--color-gray-500:#6b7280;--color-gray-600:#4b5563;--color-gray-700:#374151;--color-gray-800:#1f2937;--color-gray-900:#111827;--color-success:#059669;--color-success-light:#f0fdf4;--color-warning:#f59e0b;--color-warning-light:#fef3c7;--color-warning-text:#92400e;--color-error:#dc2626;--color-error-light:#fef2f2;--color-error-border:#fecaca;--color-error-alt:#db5050;--color-border:#e5e7eb;--color-border-light:#d1d5db;--color-border-dark:#ccc;--color-bg-primary:#fff;--color-bg-secondary:#f9fafb;--color-bg-tertiary:#f3f4f6}}
|
|
@@ -32,7 +32,7 @@ const handleForgotPassword = async () => {
|
|
|
32
32
|
} else {
|
|
33
33
|
message.value = "Failed to send password reset link.";
|
|
34
34
|
}
|
|
35
|
-
console.error(err);
|
|
35
|
+
console.error("[Nuxt Users] Forgot Password Form Error:", err);
|
|
36
36
|
isError.value = true;
|
|
37
37
|
} finally {
|
|
38
38
|
loading.value = false;
|
|
@@ -40,7 +40,7 @@ const handleSubmit = async () => {
|
|
|
40
40
|
</script>
|
|
41
41
|
|
|
42
42
|
<template>
|
|
43
|
-
<
|
|
43
|
+
<section>
|
|
44
44
|
<form @submit.prevent="handleSubmit">
|
|
45
45
|
<!-- Header slot -->
|
|
46
46
|
<slot name="header">
|
|
@@ -119,7 +119,9 @@ const handleSubmit = async () => {
|
|
|
119
119
|
<a
|
|
120
120
|
href="#"
|
|
121
121
|
class="forgot-link"
|
|
122
|
-
>
|
|
122
|
+
>
|
|
123
|
+
Forgot your password?
|
|
124
|
+
</a>
|
|
123
125
|
</p>
|
|
124
126
|
</div>
|
|
125
127
|
</slot>
|
|
@@ -137,9 +139,9 @@ const handleSubmit = async () => {
|
|
|
137
139
|
</div>
|
|
138
140
|
</slot>
|
|
139
141
|
</form>
|
|
140
|
-
</
|
|
142
|
+
</section>
|
|
141
143
|
</template>
|
|
142
144
|
|
|
143
145
|
<style scoped>
|
|
144
|
-
|
|
146
|
+
section{background:var(--color-bg-primary);border:1px solid var(--color-border);border-radius:.75em;box-shadow:0 4px 6px -1px rgba(0,0,0,.1),0 2px 4px -1px rgba(0,0,0,.06);margin:0 auto;max-width:25rem;padding:1em}form{gap:1.5rem}.form-group,form{display:flex;flex-direction:column}label{display:block;font-weight:500;margin-bottom:.5em}input[type=email],input[type=password],label{color:var(--color-gray-700);font-size:.875rem}input[type=email],input[type=password]{background-color:var(--color-bg-secondary);border:1px solid var(--color-border-light);border-radius:8px;box-sizing:border-box;padding:.75em 1em;transition:all .2s ease-in-out;width:100%}input[type=email]:focus,input[type=password]:focus{background-color:var(--color-bg-primary);border-color:var(--color-primary);box-shadow:0 0 0 3px rgba(59,130,246,.1);outline:none}.login-header{margin-bottom:1em;text-align:center}.login-title{color:var(--color-gray-800);font-size:1.875rem;font-weight:700;line-height:1.2;margin:0 0 .5em}.login-subtitle{color:var(--color-gray-500);font-size:.875rem;line-height:1.5;margin:0}.remember-me{align-items:center;display:flex;gap:.5rem}input[type=checkbox]{margin:0;width:auto}.remember-me label{color:var(--color-gray-700);font-size:.875rem;margin:0}button[type=submit]{align-items:center;background-color:var(--color-primary);border:1px solid var(--color-primary);border-radius:8px;color:var(--color-white);cursor:pointer;display:flex;font-size:.875rem;font-weight:500;gap:.5rem;justify-content:center;min-height:44px;padding:.75em 1em;transition:all .2s ease-in-out;width:100%}button[type=submit]:hover:not(:disabled){background-color:var(--color-primary-dark);border-color:var(--color-primary-dark)}button[type=submit]:disabled{cursor:not-allowed;opacity:.6}.loading-spinner{animation:spin 1s linear infinite;border:2px solid var(--color-white);border-radius:50%;border-top:2px solid transparent;height:16px;width:16px}@keyframes spin{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.login-footer{margin-top:1em;text-align:center}.forgot-password{margin:0}.forgot-link{color:var(--color-primary);font-size:.875rem;text-decoration:none;transition:color .2s ease-in-out}.forgot-link:hover{color:var(--color-primary-dark);text-decoration:underline}.error-message{background-color:var(--color-error-light);border:1px solid var(--color-error-border);border-radius:8px;color:var(--color-error);font-size:.875rem;margin-top:1em;padding:.75em 1em;text-align:center}@media (max-width:480px){.login-form-container{margin:1em;padding:1.5em}.login-title{font-size:1.5rem}}
|
|
145
147
|
</style>
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import { ref } from "vue";
|
|
3
|
+
import { navigateTo } from "#app";
|
|
4
|
+
import { useAuth } from "../composables/useAuth";
|
|
5
|
+
const props = defineProps({
|
|
6
|
+
redirectTo: { type: String, required: false, default: "/login" },
|
|
7
|
+
linkText: { type: String, required: false, default: "Logout" },
|
|
8
|
+
confirmMessage: { type: String, required: false, default: "Are you sure you want to logout?" },
|
|
9
|
+
class: { type: String, required: false }
|
|
10
|
+
});
|
|
11
|
+
const emit = defineEmits(["success", "click", "error"]);
|
|
12
|
+
const { logout } = useAuth();
|
|
13
|
+
const isLoading = ref(false);
|
|
14
|
+
const error = ref("");
|
|
15
|
+
const handleLogout = async (event) => {
|
|
16
|
+
event.preventDefault();
|
|
17
|
+
if (!confirm(props.confirmMessage)) {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
isLoading.value = true;
|
|
21
|
+
error.value = "";
|
|
22
|
+
try {
|
|
23
|
+
emit("click");
|
|
24
|
+
await logout();
|
|
25
|
+
emit("success");
|
|
26
|
+
if (props.redirectTo) {
|
|
27
|
+
await navigateTo(props.redirectTo);
|
|
28
|
+
}
|
|
29
|
+
} catch (err) {
|
|
30
|
+
const errorMessage = err instanceof Error ? err.message : "Logout failed";
|
|
31
|
+
error.value = errorMessage;
|
|
32
|
+
emit("error", errorMessage);
|
|
33
|
+
} finally {
|
|
34
|
+
isLoading.value = false;
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
</script>
|
|
38
|
+
|
|
39
|
+
<template>
|
|
40
|
+
<div>
|
|
41
|
+
<div
|
|
42
|
+
v-if="error"
|
|
43
|
+
class="error-message"
|
|
44
|
+
>
|
|
45
|
+
{{ error }}
|
|
46
|
+
</div>
|
|
47
|
+
|
|
48
|
+
<a
|
|
49
|
+
href="#"
|
|
50
|
+
:class="['logout-link', { loading: isLoading }, props.class]"
|
|
51
|
+
:disabled="isLoading"
|
|
52
|
+
@click="handleLogout"
|
|
53
|
+
>
|
|
54
|
+
<span v-if="isLoading">Logging out...</span>
|
|
55
|
+
<span v-else>{{ linkText }}</span>
|
|
56
|
+
</a>
|
|
57
|
+
</div>
|
|
58
|
+
</template>
|
|
59
|
+
|
|
60
|
+
<style scoped>
|
|
61
|
+
.logout-link{color:#dc3545;cursor:pointer;font-size:.875rem;font-weight:500;text-decoration:none;transition:color .2s}.logout-link:hover:not(.loading){color:#c82333;text-decoration:underline}.logout-link.loading{cursor:not-allowed;opacity:.6;pointer-events:none}.error-message{color:#dc3545;font-size:.875rem;margin-bottom:.5rem}
|
|
62
|
+
</style>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
interface LogoutLinkProps {
|
|
2
|
+
redirectTo?: string;
|
|
3
|
+
linkText?: string;
|
|
4
|
+
confirmMessage?: string;
|
|
5
|
+
class?: string;
|
|
6
|
+
}
|
|
7
|
+
declare const _default: import("vue").DefineComponent<LogoutLinkProps, void, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
8
|
+
click: () => any;
|
|
9
|
+
error: (error: string) => any;
|
|
10
|
+
success: () => any;
|
|
11
|
+
}, string, import("vue").PublicProps, Readonly<LogoutLinkProps> & Readonly<{
|
|
12
|
+
onClick?: (() => any) | undefined;
|
|
13
|
+
onError?: ((error: string) => any) | undefined;
|
|
14
|
+
onSuccess?: (() => any) | undefined;
|
|
15
|
+
}>, {
|
|
16
|
+
redirectTo: string;
|
|
17
|
+
linkText: string;
|
|
18
|
+
confirmMessage: string;
|
|
19
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
20
|
+
export default _default;
|
|
@@ -72,7 +72,7 @@ const handleResetPassword = async () => {
|
|
|
72
72
|
} else {
|
|
73
73
|
message.value = "Failed to reset password.";
|
|
74
74
|
}
|
|
75
|
-
console.error(err);
|
|
75
|
+
console.error("[Nuxt Users] Reset Password Form Error:", err);
|
|
76
76
|
isError.value = true;
|
|
77
77
|
} finally {
|
|
78
78
|
loading.value = false;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { useState } from "#app";
|
|
2
|
+
export const useAuth = () => {
|
|
3
|
+
const user = useState("user", () => null);
|
|
4
|
+
const logout = async () => {
|
|
5
|
+
try {
|
|
6
|
+
await $fetch("/api/logout", {
|
|
7
|
+
method: "GET"
|
|
8
|
+
});
|
|
9
|
+
user.value = null;
|
|
10
|
+
} catch (error) {
|
|
11
|
+
console.error("Logout failed:", error);
|
|
12
|
+
user.value = null;
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
return {
|
|
16
|
+
user,
|
|
17
|
+
logout
|
|
18
|
+
};
|
|
19
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { defineNuxtRouteMiddleware, useRuntimeConfig, navigateTo } from "#app";
|
|
2
|
+
import { useAuth } from "../composables/useAuth.js";
|
|
3
|
+
export default defineNuxtRouteMiddleware((to, _from) => {
|
|
4
|
+
const { nuxtUsers } = useRuntimeConfig();
|
|
5
|
+
const { user } = useAuth();
|
|
6
|
+
if (to.path === "/login") {
|
|
7
|
+
return;
|
|
8
|
+
}
|
|
9
|
+
if (!user.value && !nuxtUsers.auth?.whitelist?.includes(to.path)) {
|
|
10
|
+
return navigateTo("/login");
|
|
11
|
+
}
|
|
12
|
+
});
|
package/dist/runtime/plugin.js
CHANGED
|
@@ -3,7 +3,6 @@ import { checkTableExists } from "../utils";
|
|
|
3
3
|
export default defineNuxtPlugin(async (_nuxtApp) => {
|
|
4
4
|
const { nuxtUsers } = useRuntimeConfig();
|
|
5
5
|
const options = nuxtUsers;
|
|
6
|
-
console.log({ nuxtUsers });
|
|
7
6
|
const hasMigrationsTable = await checkTableExists(options, options.tables.migrations);
|
|
8
7
|
if (!hasMigrationsTable) {
|
|
9
8
|
console.warn("[Nuxt Users] \u26A0\uFE0F Migrations table does not exist, you should run the migration script to create it by running: npx nuxt-users migrate");
|
|
@@ -14,9 +14,9 @@ export default defineEventHandler(async (event) => {
|
|
|
14
14
|
return { message: "If a user with that email exists, a password reset link has been sent." };
|
|
15
15
|
} catch (error) {
|
|
16
16
|
if (error instanceof Error) {
|
|
17
|
-
console.error("Error in forgot-password endpoint:", error.message);
|
|
17
|
+
console.error("[Nuxt Users] Error in forgot-password endpoint:", error.message);
|
|
18
18
|
} else {
|
|
19
|
-
console.error("Error in forgot-password endpoint:", error);
|
|
19
|
+
console.error("[Nuxt Users] Error in forgot-password endpoint:", error);
|
|
20
20
|
}
|
|
21
21
|
throw createError({
|
|
22
22
|
statusCode: 500,
|
|
@@ -33,9 +33,9 @@ export default defineEventHandler(async (event) => {
|
|
|
33
33
|
}
|
|
34
34
|
} catch (error) {
|
|
35
35
|
if (error instanceof Error) {
|
|
36
|
-
console.error("Error in reset-password endpoint:", error.message);
|
|
36
|
+
console.error("[Nuxt Users] Error in reset-password endpoint:", error.message);
|
|
37
37
|
} else {
|
|
38
|
-
console.error("Error in reset-password endpoint:", error);
|
|
38
|
+
console.error("[Nuxt Users] Error in reset-password endpoint:", error);
|
|
39
39
|
}
|
|
40
40
|
if (error instanceof H3Error) {
|
|
41
41
|
throw error;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { defineEventHandler, getCookie, setCookie } from "h3";
|
|
2
|
+
import { useRuntimeConfig } from "#imports";
|
|
3
|
+
import { useDb } from "../../../utils";
|
|
4
|
+
export default defineEventHandler(async (event) => {
|
|
5
|
+
const { nuxtUsers } = useRuntimeConfig();
|
|
6
|
+
const options = nuxtUsers;
|
|
7
|
+
const db = await useDb(options);
|
|
8
|
+
const personalAccessTokensTable = options.tables.personalAccessTokens;
|
|
9
|
+
const token = getCookie(event, "auth_token");
|
|
10
|
+
if (token) {
|
|
11
|
+
await db.sql`DELETE FROM {${personalAccessTokensTable}} WHERE token = ${token}`;
|
|
12
|
+
}
|
|
13
|
+
setCookie(event, "auth_token", "", {
|
|
14
|
+
httpOnly: true,
|
|
15
|
+
secure: process.env.NODE_ENV === "production",
|
|
16
|
+
sameSite: "lax",
|
|
17
|
+
maxAge: 0,
|
|
18
|
+
path: "/"
|
|
19
|
+
});
|
|
20
|
+
return { message: "Logged out successfully" };
|
|
21
|
+
});
|
|
@@ -6,7 +6,7 @@ const TOKEN_EXPIRATION_HOURS = 1;
|
|
|
6
6
|
export const sendPasswordResetLink = async (email, options) => {
|
|
7
7
|
const user = await findUserByEmail(email, options);
|
|
8
8
|
if (!user) {
|
|
9
|
-
console.log(`Password reset requested for non-existent email: ${email}`);
|
|
9
|
+
console.log(`[Nuxt Users] Password reset requested for non-existent email: ${email}`);
|
|
10
10
|
return;
|
|
11
11
|
}
|
|
12
12
|
const db = await useDb(options);
|
|
@@ -18,7 +18,7 @@ export const sendPasswordResetLink = async (email, options) => {
|
|
|
18
18
|
VALUES (${email}, ${hashedToken}, CURRENT_TIMESTAMP)
|
|
19
19
|
`;
|
|
20
20
|
if (!options.mailer) {
|
|
21
|
-
console.error("Mailer configuration is missing. Cannot send password reset email.");
|
|
21
|
+
console.error("[Nuxt Users] Mailer configuration is missing. Cannot send password reset email.");
|
|
22
22
|
return;
|
|
23
23
|
}
|
|
24
24
|
const transporter = createTransport({
|
|
@@ -38,9 +38,9 @@ export const sendPasswordResetLink = async (email, options) => {
|
|
|
38
38
|
text: `Please click the following link to reset your password: ${options.passwordResetBaseUrl}`,
|
|
39
39
|
html: `<p>Please click the following link to reset your password:</p><p><a href="${options.passwordResetBaseUrl}">${options.passwordResetBaseUrl}</a></p><p>This link will expire in ${TOKEN_EXPIRATION_HOURS} hour(s).</p>`
|
|
40
40
|
});
|
|
41
|
-
console.log(`Password reset email sent to ${email}`);
|
|
41
|
+
console.log(`[Nuxt Users] Password reset email sent to ${email}`);
|
|
42
42
|
} catch (error) {
|
|
43
|
-
console.error(`Failed to send password reset email to ${email}:`, error);
|
|
43
|
+
console.error(`[Nuxt Users] Failed to send password reset email to ${email}:`, error);
|
|
44
44
|
}
|
|
45
45
|
};
|
|
46
46
|
export const resetPassword = async (token, email, newPassword, options) => {
|
|
@@ -52,7 +52,7 @@ export const resetPassword = async (token, email, newPassword, options) => {
|
|
|
52
52
|
ORDER BY created_at DESC
|
|
53
53
|
`;
|
|
54
54
|
if (tokenRecords.rows.length === 0) {
|
|
55
|
-
console.log(`No password reset tokens found for email: ${email}`);
|
|
55
|
+
console.log(`[Nuxt Users] No password reset tokens found for email: ${email}`);
|
|
56
56
|
return false;
|
|
57
57
|
}
|
|
58
58
|
let validTokenRecord = null;
|
|
@@ -64,7 +64,7 @@ export const resetPassword = async (token, email, newPassword, options) => {
|
|
|
64
64
|
}
|
|
65
65
|
}
|
|
66
66
|
if (!validTokenRecord || !validTokenRecord.created_at) {
|
|
67
|
-
console.log(`Invalid password reset token provided for email: ${email}`);
|
|
67
|
+
console.log(`[Nuxt Users] Invalid password reset token provided for email: ${email}`);
|
|
68
68
|
return false;
|
|
69
69
|
}
|
|
70
70
|
const now = /* @__PURE__ */ new Date();
|
|
@@ -82,13 +82,13 @@ export const resetPassword = async (token, email, newPassword, options) => {
|
|
|
82
82
|
}
|
|
83
83
|
const expirationTimeString = `${expirationYear.toString().padStart(4, "0")}-${expirationMonth.toString().padStart(2, "0")}-${expirationDay.toString().padStart(2, "0")} ${expirationHour.toString().padStart(2, "0")}:${minute.toString().padStart(2, "0")}:${second.toString().padStart(2, "0")}`;
|
|
84
84
|
if (currentTimeString > expirationTimeString) {
|
|
85
|
-
console.log(`Expired password reset token for email: ${email}`);
|
|
85
|
+
console.log(`[Nuxt Users] Expired password reset token for email: ${email}`);
|
|
86
86
|
await db.sql`DELETE FROM {${passwordResetTokensTable}} WHERE id = ${validTokenRecord.id}`;
|
|
87
87
|
return false;
|
|
88
88
|
}
|
|
89
89
|
await updateUserPassword(email, newPassword, options);
|
|
90
90
|
await db.sql`DELETE FROM {${passwordResetTokensTable}} WHERE email = ${email}`;
|
|
91
|
-
console.log(`Password reset successful for email: ${email}`);
|
|
91
|
+
console.log(`[Nuxt Users] Password reset successful for email: ${email}`);
|
|
92
92
|
return true;
|
|
93
93
|
};
|
|
94
94
|
export const deleteExpiredPasswordResetTokens = async (options) => {
|
|
@@ -101,5 +101,5 @@ export const deleteExpiredPasswordResetTokens = async (options) => {
|
|
|
101
101
|
DELETE FROM {${passwordResetTokensTable}}
|
|
102
102
|
WHERE created_at < ${expirationDateString}
|
|
103
103
|
`;
|
|
104
|
-
console.log(`Expired password reset tokens older than ${expirationDateString} deleted.`);
|
|
104
|
+
console.log(`[Nuxt Users] Expired password reset tokens older than ${expirationDateString} deleted.`);
|
|
105
105
|
};
|
|
@@ -32,7 +32,14 @@ interface ModuleOptions {
|
|
|
32
32
|
* Skip database checks during module setup to prevent hanging
|
|
33
33
|
* @default false
|
|
34
34
|
*/
|
|
35
|
-
|
|
35
|
+
auth?: {
|
|
36
|
+
/**
|
|
37
|
+
* Whitelisted routes that do not require authentication
|
|
38
|
+
* @default ['/login']
|
|
39
|
+
* @example ['/login', '/register']
|
|
40
|
+
*/
|
|
41
|
+
whitelist: string[];
|
|
42
|
+
};
|
|
36
43
|
}
|
|
37
44
|
interface MailerOptions {
|
|
38
45
|
host: string;
|
|
@@ -51,6 +58,7 @@ interface User {
|
|
|
51
58
|
email: string;
|
|
52
59
|
name: string;
|
|
53
60
|
password: string;
|
|
61
|
+
role: string;
|
|
54
62
|
created_at: string;
|
|
55
63
|
updated_at: string;
|
|
56
64
|
}
|
|
@@ -32,7 +32,14 @@ interface ModuleOptions {
|
|
|
32
32
|
* Skip database checks during module setup to prevent hanging
|
|
33
33
|
* @default false
|
|
34
34
|
*/
|
|
35
|
-
|
|
35
|
+
auth?: {
|
|
36
|
+
/**
|
|
37
|
+
* Whitelisted routes that do not require authentication
|
|
38
|
+
* @default ['/login']
|
|
39
|
+
* @example ['/login', '/register']
|
|
40
|
+
*/
|
|
41
|
+
whitelist: string[];
|
|
42
|
+
};
|
|
36
43
|
}
|
|
37
44
|
interface MailerOptions {
|
|
38
45
|
host: string;
|
|
@@ -51,6 +58,7 @@ interface User {
|
|
|
51
58
|
email: string;
|
|
52
59
|
name: string;
|
|
53
60
|
password: string;
|
|
61
|
+
role: string;
|
|
54
62
|
created_at: string;
|
|
55
63
|
updated_at: string;
|
|
56
64
|
}
|
|
@@ -33,7 +33,7 @@ const useDb = async (options) => {
|
|
|
33
33
|
try {
|
|
34
34
|
return createDatabase(connector(connectorOptions));
|
|
35
35
|
} catch (error) {
|
|
36
|
-
console.warn(`[Nuxt Users
|
|
36
|
+
console.warn(`[Nuxt Users] \u26A0\uFE0F Failed to connect to ${connectorName} database:`, error instanceof Error ? error.message : "Unknown error");
|
|
37
37
|
throw error;
|
|
38
38
|
}
|
|
39
39
|
};
|
|
@@ -51,11 +51,12 @@ const createUser = async (userData, options) => {
|
|
|
51
51
|
const db = await useDb(options);
|
|
52
52
|
const usersTable = options.tables.users;
|
|
53
53
|
const hashedPassword = await bcrypt.hash(userData.password, 10);
|
|
54
|
+
const role = userData.role || "user";
|
|
54
55
|
await db.sql`
|
|
55
|
-
INSERT INTO {${usersTable}} (email, name, password, created_at, updated_at)
|
|
56
|
-
VALUES (${userData.email}, ${userData.name}, ${hashedPassword}, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)
|
|
56
|
+
INSERT INTO {${usersTable}} (email, name, password, role, created_at, updated_at)
|
|
57
|
+
VALUES (${userData.email}, ${userData.name}, ${hashedPassword}, ${role}, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)
|
|
57
58
|
`;
|
|
58
|
-
const result = await db.sql`SELECT id, email, name, created_at, updated_at FROM {${usersTable}} WHERE email = ${userData.email}`;
|
|
59
|
+
const result = await db.sql`SELECT id, email, name, role, created_at, updated_at FROM {${usersTable}} WHERE email = ${userData.email}`;
|
|
59
60
|
if (result.rows.length === 0) {
|
|
60
61
|
throw new Error("Failed to retrieve created user.");
|
|
61
62
|
}
|
|
@@ -64,6 +65,7 @@ const createUser = async (userData, options) => {
|
|
|
64
65
|
id: user.id,
|
|
65
66
|
email: user.email,
|
|
66
67
|
name: user.name,
|
|
68
|
+
role: user.role,
|
|
67
69
|
created_at: user.created_at instanceof Date ? user.created_at.toISOString() : user.created_at,
|
|
68
70
|
updated_at: user.updated_at instanceof Date ? user.updated_at.toISOString() : user.updated_at
|
|
69
71
|
};
|
|
@@ -81,6 +83,7 @@ const findUserByEmail = async (email, options) => {
|
|
|
81
83
|
email: user.email,
|
|
82
84
|
name: user.name,
|
|
83
85
|
password: user.password,
|
|
86
|
+
role: user.role,
|
|
84
87
|
created_at: user.created_at instanceof Date ? user.created_at.toISOString() : user.created_at,
|
|
85
88
|
updated_at: user.updated_at instanceof Date ? user.updated_at.toISOString() : user.updated_at
|
|
86
89
|
};
|
|
@@ -100,7 +103,7 @@ const createUsersTable = async (options) => {
|
|
|
100
103
|
const connectorName = options.connector.name;
|
|
101
104
|
const db = await useDb(options);
|
|
102
105
|
const tableName = options.tables.users;
|
|
103
|
-
console.log(`[DB:Create ${connectorName} Users Table
|
|
106
|
+
console.log(`[Nuxt Users] DB:Create ${connectorName} Users Table Creating ${tableName}...`);
|
|
104
107
|
if (connectorName === "sqlite") {
|
|
105
108
|
await db.sql`
|
|
106
109
|
CREATE TABLE IF NOT EXISTS {${tableName}} (
|
|
@@ -108,6 +111,7 @@ const createUsersTable = async (options) => {
|
|
|
108
111
|
email TEXT NOT NULL UNIQUE,
|
|
109
112
|
name TEXT NOT NULL,
|
|
110
113
|
password TEXT NOT NULL,
|
|
114
|
+
role TEXT NOT NULL DEFAULT 'user',
|
|
111
115
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
112
116
|
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
113
117
|
)
|
|
@@ -120,6 +124,7 @@ const createUsersTable = async (options) => {
|
|
|
120
124
|
email VARCHAR(255) NOT NULL UNIQUE,
|
|
121
125
|
name VARCHAR(255) NOT NULL,
|
|
122
126
|
password VARCHAR(255) NOT NULL,
|
|
127
|
+
role VARCHAR(32) NOT NULL DEFAULT 'user',
|
|
123
128
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
124
129
|
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
125
130
|
)
|
|
@@ -132,19 +137,20 @@ const createUsersTable = async (options) => {
|
|
|
132
137
|
email VARCHAR(255) NOT NULL UNIQUE,
|
|
133
138
|
name VARCHAR(255) NOT NULL,
|
|
134
139
|
password VARCHAR(255) NOT NULL,
|
|
140
|
+
role VARCHAR(32) NOT NULL DEFAULT 'user',
|
|
135
141
|
created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
|
|
136
142
|
updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP
|
|
137
143
|
)
|
|
138
144
|
`;
|
|
139
145
|
}
|
|
140
|
-
console.log(`[DB:Create ${connectorName} Users Table
|
|
146
|
+
console.log(`[Nuxt Users] DB:Create ${connectorName} Users Table Fields: id, email, name, password, role, created_at, updated_at \u2705`);
|
|
141
147
|
};
|
|
142
148
|
|
|
143
149
|
const createPersonalAccessTokensTable = async (options) => {
|
|
144
150
|
const connectorName = options.connector.name;
|
|
145
151
|
const db = await useDb(options);
|
|
146
152
|
const tableName = options.tables.personalAccessTokens;
|
|
147
|
-
console.log(`[DB:Create Personal Access Tokens ${connectorName} Table
|
|
153
|
+
console.log(`[Nuxt Users] DB:Create Personal Access Tokens ${connectorName} Table Creating ${tableName} table with ${connectorName} connector...`);
|
|
148
154
|
if (connectorName === "sqlite") {
|
|
149
155
|
await db.sql`
|
|
150
156
|
CREATE TABLE IF NOT EXISTS {${tableName}} (
|
|
@@ -193,14 +199,14 @@ const createPersonalAccessTokensTable = async (options) => {
|
|
|
193
199
|
)
|
|
194
200
|
`;
|
|
195
201
|
}
|
|
196
|
-
console.log(`[DB:Create Personal Access Tokens ${connectorName} Table
|
|
202
|
+
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`);
|
|
197
203
|
};
|
|
198
204
|
|
|
199
205
|
const createPasswordResetTokensTable = async (options) => {
|
|
200
206
|
const connectorName = options.connector.name;
|
|
201
207
|
const db = await useDb(options);
|
|
202
208
|
const tableName = options.tables.passwordResetTokens;
|
|
203
|
-
console.log(`[DB:Create Password Reset Tokens ${connectorName} Table
|
|
209
|
+
console.log(`[Nuxt Users] DB:Create Password Reset Tokens ${connectorName} Table Creating ${tableName} table with ${connectorName} connector...`);
|
|
204
210
|
if (connectorName === "sqlite") {
|
|
205
211
|
await db.sql`
|
|
206
212
|
CREATE TABLE IF NOT EXISTS {${tableName}} (
|
|
@@ -233,14 +239,14 @@ const createPasswordResetTokensTable = async (options) => {
|
|
|
233
239
|
}
|
|
234
240
|
await db.sql`CREATE INDEX IF NOT EXISTS idx_password_reset_tokens_email ON {${tableName}} (email)`;
|
|
235
241
|
await db.sql`CREATE INDEX IF NOT EXISTS idx_password_reset_tokens_token ON {${tableName}} (token)`;
|
|
236
|
-
console.log(`[DB:Create Password Reset Tokens ${connectorName} Table
|
|
242
|
+
console.log(`[Nuxt Users] DB:Create Password Reset Tokens ${connectorName} Table Fields: id, email, token, created_at \u2705`);
|
|
237
243
|
};
|
|
238
244
|
|
|
239
245
|
const createMigrationsTable = async (options) => {
|
|
240
246
|
const connectorName = options.connector.name;
|
|
241
247
|
const db = await useDb(options);
|
|
242
248
|
const tableName = "migrations";
|
|
243
|
-
console.log(`[DB:Create Migrations ${connectorName} Table
|
|
249
|
+
console.log(`[Nuxt Users] DB:Create Migrations ${connectorName} Table Creating ${tableName} table with ${connectorName} connector...`);
|
|
244
250
|
if (connectorName === "sqlite") {
|
|
245
251
|
await db.sql`
|
|
246
252
|
CREATE TABLE IF NOT EXISTS {${tableName}} (
|
|
@@ -268,7 +274,7 @@ const createMigrationsTable = async (options) => {
|
|
|
268
274
|
)
|
|
269
275
|
`;
|
|
270
276
|
}
|
|
271
|
-
console.log(`[DB:Create Migrations ${connectorName} Table
|
|
277
|
+
console.log(`[Nuxt Users] DB:Create Migrations ${connectorName} Table successfull \u2705`);
|
|
272
278
|
};
|
|
273
279
|
|
|
274
280
|
const migrations = [
|
|
@@ -314,7 +320,7 @@ const runMigrations = async (options) => {
|
|
|
314
320
|
}
|
|
315
321
|
console.log(`[Nuxt Users] Found ${pendingMigrations.length} pending migrations:`);
|
|
316
322
|
pendingMigrations.forEach((migration) => {
|
|
317
|
-
console.log(`
|
|
323
|
+
console.log(`[Nuxt Users] - ${migration.name}`);
|
|
318
324
|
});
|
|
319
325
|
for (const migration of pendingMigrations) {
|
|
320
326
|
console.log(`[Nuxt Users] Running migration: ${migration.name}`);
|
package/dist/utils.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as db0 from 'db0';
|
|
2
|
-
import { M as ModuleOptions, U as User } from './shared/nuxt-users.
|
|
2
|
+
import { M as ModuleOptions, U as User } from './shared/nuxt-users.DGRKT2Tq.mjs';
|
|
3
3
|
|
|
4
4
|
declare const useDb: (options: ModuleOptions) => Promise<db0.Database<db0.Connector<Database.Database>>>;
|
|
5
5
|
declare const checkTableExists: (options: ModuleOptions, tableName: string) => Promise<boolean>;
|
|
@@ -8,6 +8,7 @@ interface CreateUserParams {
|
|
|
8
8
|
email: string;
|
|
9
9
|
name: string;
|
|
10
10
|
password: string;
|
|
11
|
+
role?: string;
|
|
11
12
|
}
|
|
12
13
|
/**
|
|
13
14
|
* Creates a new user in the database.
|
package/dist/utils.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as db0 from 'db0';
|
|
2
|
-
import { M as ModuleOptions, U as User } from './shared/nuxt-users.
|
|
2
|
+
import { M as ModuleOptions, U as User } from './shared/nuxt-users.DGRKT2Tq.js';
|
|
3
3
|
|
|
4
4
|
declare const useDb: (options: ModuleOptions) => Promise<db0.Database<db0.Connector<Database.Database>>>;
|
|
5
5
|
declare const checkTableExists: (options: ModuleOptions, tableName: string) => Promise<boolean>;
|
|
@@ -8,6 +8,7 @@ interface CreateUserParams {
|
|
|
8
8
|
email: string;
|
|
9
9
|
name: string;
|
|
10
10
|
password: string;
|
|
11
|
+
role?: string;
|
|
11
12
|
}
|
|
12
13
|
/**
|
|
13
14
|
* Creates a new user in the database.
|
package/dist/utils.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { c as checkTableExists, h as createMigrationsTable, g as createPasswordResetTokensTable, e as createPersonalAccessTokensTable, a as createUser, d as createUsersTable, f as findUserByEmail, r as runMigrations, b as updateUserPassword, u as useDb } from './shared/nuxt-users.
|
|
1
|
+
export { c as checkTableExists, h as createMigrationsTable, g as createPasswordResetTokensTable, e as createPersonalAccessTokensTable, a as createUser, d as createUsersTable, f as findUserByEmail, r as runMigrations, b as updateUserPassword, u as useDb } from './shared/nuxt-users.DZkU2AbH.mjs';
|
|
2
2
|
import 'bcrypt';
|
|
3
3
|
import 'db0';
|