nuxt-users 1.15.5 → 1.16.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 +30 -0
- package/dist/cli.mjs +21 -1
- package/dist/module.d.mts +1 -1
- package/dist/module.d.ts +1 -1
- package/dist/module.json +1 -1
- package/dist/runtime/components/NUsersList.vue.d.ts +1 -0
- package/dist/runtime/composables/useAuthentication.d.ts +2 -0
- package/dist/runtime/server/api/nuxt-users/[id].patch.js +7 -0
- package/dist/runtime/server/api/nuxt-users/inactive.get.d.ts +20 -0
- package/dist/runtime/server/api/nuxt-users/inactive.get.js +59 -0
- package/dist/runtime/server/api/nuxt-users/index.get.js +2 -1
- package/dist/runtime/server/api/nuxt-users/session/index.post.d.ts +1 -0
- package/dist/runtime/server/api/nuxt-users/session/index.post.js +6 -0
- package/dist/runtime/server/utils/add-active-to-users.d.ts +2 -0
- package/dist/runtime/server/utils/add-active-to-users.js +23 -0
- package/dist/runtime/server/utils/migrate.js +5 -0
- package/dist/runtime/server/utils/user.d.ts +1 -0
- package/dist/runtime/server/utils/user.js +13 -5
- package/dist/shared/{nuxt-users.u7N4meyI.d.mts → nuxt-users.CAfpTSaE.d.mts} +1 -0
- package/dist/shared/{nuxt-users.u7N4meyI.d.ts → nuxt-users.CAfpTSaE.d.ts} +1 -0
- package/dist/utils.d.mts +1 -1
- package/dist/utils.d.ts +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,36 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
3
|
|
|
4
|
+
## v1.16.0
|
|
5
|
+
|
|
6
|
+
[compare changes](https://github.com/rrd108/nuxt-users/compare/v1.15.5...v1.16.0)
|
|
7
|
+
|
|
8
|
+
### 🚀 Enhancements
|
|
9
|
+
|
|
10
|
+
- Add inactive user functionality ([67f8fbe](https://github.com/rrd108/nuxt-users/commit/67f8fbe))
|
|
11
|
+
|
|
12
|
+
### 🩹 Fixes
|
|
13
|
+
|
|
14
|
+
- Exposed server utils ([abe8f20](https://github.com/rrd108/nuxt-users/commit/abe8f20))
|
|
15
|
+
|
|
16
|
+
### 💅 Refactors
|
|
17
|
+
|
|
18
|
+
- Exports ([db41f7c](https://github.com/rrd108/nuxt-users/commit/db41f7c))
|
|
19
|
+
|
|
20
|
+
### 🏡 Chore
|
|
21
|
+
|
|
22
|
+
- **release:** V1.15.5 ([8e9e665](https://github.com/rrd108/nuxt-users/commit/8e9e665))
|
|
23
|
+
- Fixes formatting issue in test file ([bfdc4d2](https://github.com/rrd108/nuxt-users/commit/bfdc4d2))
|
|
24
|
+
|
|
25
|
+
### ✅ Tests
|
|
26
|
+
|
|
27
|
+
- Fix failing test ([4a0f9e4](https://github.com/rrd108/nuxt-users/commit/4a0f9e4))
|
|
28
|
+
- Fix postgres connection error ([eae0b33](https://github.com/rrd108/nuxt-users/commit/eae0b33))
|
|
29
|
+
|
|
30
|
+
### ❤️ Contributors
|
|
31
|
+
|
|
32
|
+
- Rrd108 ([@rrd108](https://github.com/rrd108))
|
|
33
|
+
|
|
4
34
|
## v1.15.5
|
|
5
35
|
|
|
6
36
|
[compare changes](https://github.com/rrd108/nuxt-users/compare/v1.15.4...v1.15.5)
|
package/dist/cli.mjs
CHANGED
|
@@ -5,6 +5,7 @@ import { loadNuxt } from '@nuxt/kit';
|
|
|
5
5
|
import { defu } from 'defu';
|
|
6
6
|
import { runMigrations, createUser as createUser$1, createUsersTable as createUsersTable$1, createPersonalAccessTokensTable as createPersonalAccessTokensTable$1, createPasswordResetTokensTable as createPasswordResetTokensTable$1, createMigrationsTable as createMigrationsTable$1 } from '../dist/runtime/server/utils/index.js';
|
|
7
7
|
import { getPasswordValidationOptions, validatePassword } from './utils.mjs';
|
|
8
|
+
import { addActiveToUsers as addActiveToUsers$1 } from '../dist/runtime/server/utils/add-active-to-users.js';
|
|
8
9
|
import '../dist/runtime/server/internal/index.js';
|
|
9
10
|
|
|
10
11
|
const getOptionsFromEnv = () => {
|
|
@@ -208,6 +209,24 @@ const createMigrationsTable = defineCommand({
|
|
|
208
209
|
}
|
|
209
210
|
});
|
|
210
211
|
|
|
212
|
+
const addActiveToUsers = defineCommand({
|
|
213
|
+
meta: {
|
|
214
|
+
name: "add-active-to-users",
|
|
215
|
+
description: "Add the active field to the users table in the database"
|
|
216
|
+
},
|
|
217
|
+
async run() {
|
|
218
|
+
console.log("[Nuxt Users] Adding active field to users table...");
|
|
219
|
+
const options = await loadOptions();
|
|
220
|
+
try {
|
|
221
|
+
await addActiveToUsers$1(options);
|
|
222
|
+
console.log("[Nuxt Users] Active field added to users table successfully!");
|
|
223
|
+
} catch (error) {
|
|
224
|
+
console.error("[Nuxt Users] DB:Add Active to Users Error:", error);
|
|
225
|
+
process.exit(1);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
});
|
|
229
|
+
|
|
211
230
|
const projectInfo = defineCommand({
|
|
212
231
|
meta: {
|
|
213
232
|
name: "project-info",
|
|
@@ -248,7 +267,7 @@ const main = defineCommand({
|
|
|
248
267
|
meta: {
|
|
249
268
|
name: "nuxt-users",
|
|
250
269
|
description: "CLI for Nuxt Users Module - Manage users, migrations, and database operations",
|
|
251
|
-
version: "1.15.
|
|
270
|
+
version: "1.15.5"
|
|
252
271
|
},
|
|
253
272
|
subCommands: {
|
|
254
273
|
migrate,
|
|
@@ -257,6 +276,7 @@ const main = defineCommand({
|
|
|
257
276
|
"create-personal-access-tokens-table": createPersonalAccessTokensTable,
|
|
258
277
|
"create-password-reset-tokens-table": createPasswordResetTokensTable,
|
|
259
278
|
"create-migrations-table": createMigrationsTable,
|
|
279
|
+
"add-active-to-users": addActiveToUsers,
|
|
260
280
|
"project-info": projectInfo
|
|
261
281
|
}
|
|
262
282
|
});
|
package/dist/module.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as _nuxt_schema from '@nuxt/schema';
|
|
2
|
-
import { R as RuntimeModuleOptions, M as ModuleOptions } from './shared/nuxt-users.
|
|
2
|
+
import { R as RuntimeModuleOptions, M as ModuleOptions } from './shared/nuxt-users.CAfpTSaE.mjs';
|
|
3
3
|
export * from '../dist/runtime/server/internal/index.js';
|
|
4
4
|
|
|
5
5
|
declare const defaultOptions: ModuleOptions;
|
package/dist/module.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as _nuxt_schema from '@nuxt/schema';
|
|
2
|
-
import { R as RuntimeModuleOptions, M as ModuleOptions } from './shared/nuxt-users.
|
|
2
|
+
import { R as RuntimeModuleOptions, M as ModuleOptions } from './shared/nuxt-users.CAfpTSaE.js';
|
|
3
3
|
export * from '../dist/runtime/server/internal/index.js';
|
|
4
4
|
|
|
5
5
|
declare const defaultOptions: ModuleOptions;
|
package/dist/module.json
CHANGED
|
@@ -5,6 +5,7 @@ export declare const useAuthentication: () => {
|
|
|
5
5
|
readonly email: string;
|
|
6
6
|
readonly name: string;
|
|
7
7
|
readonly role: string;
|
|
8
|
+
readonly active: boolean;
|
|
8
9
|
readonly created_at: string;
|
|
9
10
|
readonly updated_at: string;
|
|
10
11
|
readonly last_login_at?: string | undefined;
|
|
@@ -13,6 +14,7 @@ export declare const useAuthentication: () => {
|
|
|
13
14
|
readonly email: string;
|
|
14
15
|
readonly name: string;
|
|
15
16
|
readonly role: string;
|
|
17
|
+
readonly active: boolean;
|
|
16
18
|
readonly created_at: string;
|
|
17
19
|
readonly updated_at: string;
|
|
18
20
|
readonly last_login_at?: string | undefined;
|
|
@@ -12,6 +12,13 @@ export default defineEventHandler(async (event) => {
|
|
|
12
12
|
});
|
|
13
13
|
}
|
|
14
14
|
const body = await readBody(event);
|
|
15
|
+
const currentUser = event.context.user;
|
|
16
|
+
if (currentUser && currentUser.id === userId && typeof body.active !== "undefined") {
|
|
17
|
+
throw createError({
|
|
18
|
+
statusCode: 403,
|
|
19
|
+
statusMessage: "You cannot change your own active status."
|
|
20
|
+
});
|
|
21
|
+
}
|
|
15
22
|
try {
|
|
16
23
|
const updatedUser = await updateUser(userId, body, options);
|
|
17
24
|
return { user: updatedUser };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<{
|
|
2
|
+
users: {
|
|
3
|
+
id: number;
|
|
4
|
+
email: string;
|
|
5
|
+
name: string;
|
|
6
|
+
role: string;
|
|
7
|
+
created_at: string;
|
|
8
|
+
updated_at: string;
|
|
9
|
+
last_login_at: string | null;
|
|
10
|
+
}[];
|
|
11
|
+
pagination: {
|
|
12
|
+
page: number;
|
|
13
|
+
limit: number;
|
|
14
|
+
total: number;
|
|
15
|
+
totalPages: number;
|
|
16
|
+
hasNext: boolean;
|
|
17
|
+
hasPrev: boolean;
|
|
18
|
+
};
|
|
19
|
+
}>>;
|
|
20
|
+
export default _default;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { createError, defineEventHandler, getQuery } from "h3";
|
|
2
|
+
import { useRuntimeConfig } from "#imports";
|
|
3
|
+
import { useDb } from "../../utils/db.js";
|
|
4
|
+
import { getLastLoginTime } from "../../utils/user.js";
|
|
5
|
+
export default defineEventHandler(async (event) => {
|
|
6
|
+
const { nuxtUsers } = useRuntimeConfig();
|
|
7
|
+
const options = nuxtUsers;
|
|
8
|
+
const db = await useDb(options);
|
|
9
|
+
const usersTable = options.tables.users;
|
|
10
|
+
const query = getQuery(event);
|
|
11
|
+
const page = Number(query.page) || 1;
|
|
12
|
+
const limit = Number(query.limit) || 10;
|
|
13
|
+
const offset = (page - 1) * limit;
|
|
14
|
+
if (page < 1 || limit < 1 || limit > 100) {
|
|
15
|
+
throw createError({
|
|
16
|
+
statusCode: 400,
|
|
17
|
+
statusMessage: "Invalid pagination parameters. Page must be >= 1, limit must be between 1 and 100."
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
try {
|
|
21
|
+
const countResult = await db.sql`SELECT COUNT(*) as total FROM {${usersTable}} WHERE active = FALSE`;
|
|
22
|
+
const total = countResult.rows[0].total;
|
|
23
|
+
const usersResult = await db.sql`
|
|
24
|
+
SELECT id, email, name, role, created_at, updated_at
|
|
25
|
+
FROM {${usersTable}}
|
|
26
|
+
WHERE active = FALSE
|
|
27
|
+
ORDER BY name ASC
|
|
28
|
+
LIMIT ${limit} OFFSET ${offset}
|
|
29
|
+
`;
|
|
30
|
+
const users = await Promise.all(usersResult.rows.map(async (user) => {
|
|
31
|
+
const lastLoginTime = await getLastLoginTime(user.id, options);
|
|
32
|
+
return {
|
|
33
|
+
id: user.id,
|
|
34
|
+
email: user.email,
|
|
35
|
+
name: user.name,
|
|
36
|
+
role: user.role,
|
|
37
|
+
created_at: user.created_at instanceof Date ? user.created_at.toISOString() : user.created_at,
|
|
38
|
+
updated_at: user.updated_at instanceof Date ? user.updated_at.toISOString() : user.updated_at,
|
|
39
|
+
last_login_at: lastLoginTime
|
|
40
|
+
};
|
|
41
|
+
}));
|
|
42
|
+
return {
|
|
43
|
+
users,
|
|
44
|
+
pagination: {
|
|
45
|
+
page,
|
|
46
|
+
limit,
|
|
47
|
+
total,
|
|
48
|
+
totalPages: Math.ceil(total / limit),
|
|
49
|
+
hasNext: page * limit < total,
|
|
50
|
+
hasPrev: page > 1
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
} catch (error) {
|
|
54
|
+
throw createError({
|
|
55
|
+
statusCode: 500,
|
|
56
|
+
statusMessage: `Error fetching users: ${error instanceof Error ? error.message : String(error)}`
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
});
|
|
@@ -18,11 +18,12 @@ export default defineEventHandler(async (event) => {
|
|
|
18
18
|
});
|
|
19
19
|
}
|
|
20
20
|
try {
|
|
21
|
-
const countResult = await db.sql`SELECT COUNT(*) as total FROM {${usersTable}}`;
|
|
21
|
+
const countResult = await db.sql`SELECT COUNT(*) as total FROM {${usersTable}} WHERE active = TRUE`;
|
|
22
22
|
const total = countResult.rows[0].total;
|
|
23
23
|
const usersResult = await db.sql`
|
|
24
24
|
SELECT id, email, name, role, created_at, updated_at
|
|
25
25
|
FROM {${usersTable}}
|
|
26
|
+
WHERE active = TRUE
|
|
26
27
|
ORDER BY name ASC
|
|
27
28
|
LIMIT ${limit} OFFSET ${offset}
|
|
28
29
|
`;
|
|
@@ -25,6 +25,12 @@ export default defineEventHandler(async (event) => {
|
|
|
25
25
|
});
|
|
26
26
|
}
|
|
27
27
|
const user = userResult.rows[0];
|
|
28
|
+
if (!user.active) {
|
|
29
|
+
throw createError({
|
|
30
|
+
statusCode: 403,
|
|
31
|
+
statusMessage: "User account is inactive"
|
|
32
|
+
});
|
|
33
|
+
}
|
|
28
34
|
const storedPassword = user.password;
|
|
29
35
|
const passwordMatch = await bcrypt.compare(password, storedPassword);
|
|
30
36
|
if (!passwordMatch) {
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { useDb } from "./db.js";
|
|
2
|
+
export const addActiveToUsers = async (options) => {
|
|
3
|
+
const connectorName = options.connector.name;
|
|
4
|
+
const db = await useDb(options);
|
|
5
|
+
const tableName = options.tables.users;
|
|
6
|
+
console.log(`[Nuxt Users] DB:Add active to ${connectorName} Users Table in ${tableName}...`);
|
|
7
|
+
if (connectorName === "sqlite" || connectorName === "mysql" || connectorName === "postgresql") {
|
|
8
|
+
try {
|
|
9
|
+
const result = await db.sql`PRAGMA table_info({${tableName}})`;
|
|
10
|
+
const hasActiveColumn = result.rows.some((row) => row.name === "active");
|
|
11
|
+
if (!hasActiveColumn) {
|
|
12
|
+
await db.sql`ALTER TABLE {${tableName}} ADD COLUMN active BOOLEAN DEFAULT TRUE`;
|
|
13
|
+
}
|
|
14
|
+
} catch {
|
|
15
|
+
try {
|
|
16
|
+
await db.sql`ALTER TABLE {${tableName}} ADD COLUMN active BOOLEAN DEFAULT TRUE`;
|
|
17
|
+
} catch (alterError) {
|
|
18
|
+
console.log(`[Nuxt Users] Active column might already exist: ${alterError}`);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
console.log(`[Nuxt Users] DB:Add active to ${connectorName} Users Table \u2705`);
|
|
23
|
+
};
|
|
@@ -3,6 +3,7 @@ import { createUsersTable } from "./create-users-table.js";
|
|
|
3
3
|
import { createPersonalAccessTokensTable } from "./create-personal-access-tokens-table.js";
|
|
4
4
|
import { createPasswordResetTokensTable } from "./create-password-reset-tokens-table.js";
|
|
5
5
|
import { createMigrationsTable } from "./create-migrations-table.js";
|
|
6
|
+
import { addActiveToUsers } from "./add-active-to-users.js";
|
|
6
7
|
const migrations = [
|
|
7
8
|
{
|
|
8
9
|
name: "create_migrations_table",
|
|
@@ -19,6 +20,10 @@ const migrations = [
|
|
|
19
20
|
{
|
|
20
21
|
name: "create_password_reset_tokens_table",
|
|
21
22
|
run: createPasswordResetTokensTable
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
name: "add_active_to_users",
|
|
26
|
+
run: addActiveToUsers
|
|
22
27
|
}
|
|
23
28
|
];
|
|
24
29
|
export const getAppliedMigrations = async (options) => {
|
|
@@ -15,7 +15,7 @@ export const createUser = async (userData, options) => {
|
|
|
15
15
|
INSERT INTO {${usersTable}} (email, name, password, role, created_at, updated_at)
|
|
16
16
|
VALUES (${userData.email}, ${userData.name}, ${hashedPassword}, ${role}, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)
|
|
17
17
|
`;
|
|
18
|
-
const result = await db.sql`SELECT id, email, name, role, created_at, updated_at FROM {${usersTable}} WHERE email = ${userData.email}`;
|
|
18
|
+
const result = await db.sql`SELECT id, email, name, role, created_at, updated_at, active FROM {${usersTable}} WHERE email = ${userData.email}`;
|
|
19
19
|
if (result.rows.length === 0) {
|
|
20
20
|
throw new Error("Failed to retrieve created user.");
|
|
21
21
|
}
|
|
@@ -26,7 +26,8 @@ export const createUser = async (userData, options) => {
|
|
|
26
26
|
name: user.name,
|
|
27
27
|
role: user.role,
|
|
28
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
|
|
29
|
+
updated_at: user.updated_at instanceof Date ? user.updated_at.toISOString() : user.updated_at,
|
|
30
|
+
active: user.active
|
|
30
31
|
};
|
|
31
32
|
};
|
|
32
33
|
export const findUserByEmail = async (email, options) => {
|
|
@@ -43,8 +44,9 @@ export const findUserByEmail = async (email, options) => {
|
|
|
43
44
|
name: user.name,
|
|
44
45
|
password: user.password,
|
|
45
46
|
role: user.role,
|
|
46
|
-
created_at: user.created_at
|
|
47
|
-
updated_at: user.updated_at
|
|
47
|
+
created_at: user.created_at,
|
|
48
|
+
updated_at: user.updated_at,
|
|
49
|
+
active: user.active
|
|
48
50
|
};
|
|
49
51
|
};
|
|
50
52
|
export const findUserById = async (id, options, withPass = false) => {
|
|
@@ -69,7 +71,7 @@ export const findUserById = async (id, options, withPass = false) => {
|
|
|
69
71
|
export const updateUser = async (id, userData, options) => {
|
|
70
72
|
const db = await useDb(options);
|
|
71
73
|
const usersTable = options.tables.users;
|
|
72
|
-
const allowedFields = ["name", "email", "role"];
|
|
74
|
+
const allowedFields = ["name", "email", "role", "active"];
|
|
73
75
|
const updates = [];
|
|
74
76
|
const values = [];
|
|
75
77
|
for (const field of allowedFields) {
|
|
@@ -78,6 +80,9 @@ export const updateUser = async (id, userData, options) => {
|
|
|
78
80
|
values.push(userData[field]);
|
|
79
81
|
}
|
|
80
82
|
}
|
|
83
|
+
if (userData.active === false) {
|
|
84
|
+
await revokeUserTokens(id, options);
|
|
85
|
+
}
|
|
81
86
|
if (updates.length === 0) {
|
|
82
87
|
const currentUser = await findUserById(id, options);
|
|
83
88
|
if (!currentUser) {
|
|
@@ -153,6 +158,9 @@ export const getCurrentUserFromToken = async (token, options, withPass = false)
|
|
|
153
158
|
return null;
|
|
154
159
|
}
|
|
155
160
|
const user = userResult.rows[0];
|
|
161
|
+
if (!user.active) {
|
|
162
|
+
return null;
|
|
163
|
+
}
|
|
156
164
|
if (withPass === true) {
|
|
157
165
|
return user;
|
|
158
166
|
}
|
package/dist/utils.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { L as LoginFormData, M as ModuleOptions, b as PasswordResetToken, P as PersonalAccessToken, U as User, a as UserWithoutPassword } from './shared/nuxt-users.
|
|
1
|
+
export { L as LoginFormData, M as ModuleOptions, b as PasswordResetToken, P as PersonalAccessToken, U as User, a as UserWithoutPassword } from './shared/nuxt-users.CAfpTSaE.mjs';
|
|
2
2
|
|
|
3
3
|
interface PasswordValidationResult {
|
|
4
4
|
isValid: boolean;
|
package/dist/utils.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { L as LoginFormData, M as ModuleOptions, b as PasswordResetToken, P as PersonalAccessToken, U as User, a as UserWithoutPassword } from './shared/nuxt-users.
|
|
1
|
+
export { L as LoginFormData, M as ModuleOptions, b as PasswordResetToken, P as PersonalAccessToken, U as User, a as UserWithoutPassword } from './shared/nuxt-users.CAfpTSaE.js';
|
|
2
2
|
|
|
3
3
|
interface PasswordValidationResult {
|
|
4
4
|
isValid: boolean;
|
package/package.json
CHANGED