nuxt-users 1.22.0 → 1.23.1

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 CHANGED
@@ -1,6 +1,59 @@
1
1
  # Changelog
2
2
 
3
3
 
4
+ ## v1.23.1
5
+
6
+ [compare changes](https://github.com/rrd108/nuxt-users/compare/v1.23.0...v1.23.1)
7
+
8
+ ### 🩹 Fixes
9
+
10
+ - User patch sql error ([aa506dd](https://github.com/rrd108/nuxt-users/commit/aa506dd))
11
+
12
+ ### 💅 Refactors
13
+
14
+ - Change css class name ([1bc28ba](https://github.com/rrd108/nuxt-users/commit/1bc28ba))
15
+
16
+ ### ✅ Tests
17
+
18
+ - New test script added ([618b8dc](https://github.com/rrd108/nuxt-users/commit/618b8dc))
19
+
20
+ ### ❤️ Contributors
21
+
22
+ - Rrd108 ([@rrd108](https://github.com/rrd108))
23
+
24
+ ## v1.23.0
25
+
26
+ [compare changes](https://github.com/rrd108/nuxt-users/compare/v1.22.0...v1.23.0)
27
+
28
+ ### 🚀 Enhancements
29
+
30
+ - Password reset url is configurable ([0a3d443](https://github.com/rrd108/nuxt-users/commit/0a3d443))
31
+ - Adds programmatic access control ([8bb517a](https://github.com/rrd108/nuxt-users/commit/8bb517a))
32
+
33
+ ### 💅 Refactors
34
+
35
+ - Vue SFC type resolution during module build ([533fa36](https://github.com/rrd108/nuxt-users/commit/533fa36))
36
+
37
+ ### 📖 Documentation
38
+
39
+ - Reset-password page info added ([9b4e6c2](https://github.com/rrd108/nuxt-users/commit/9b4e6c2))
40
+
41
+ ### 🏡 Chore
42
+
43
+ - Update ip ([3139eab](https://github.com/rrd108/nuxt-users/commit/3139eab))
44
+ - Removes unused import ([61089b4](https://github.com/rrd108/nuxt-users/commit/61089b4))
45
+ - Unused imort removed ([3f3012f](https://github.com/rrd108/nuxt-users/commit/3f3012f))
46
+ - Remove unsued import ([ae1f4e3](https://github.com/rrd108/nuxt-users/commit/ae1f4e3))
47
+ - **release:** V1.22.0 ([914844f](https://github.com/rrd108/nuxt-users/commit/914844f))
48
+
49
+ ### ✅ Tests
50
+
51
+ - Fix test cases ([844c3a7](https://github.com/rrd108/nuxt-users/commit/844c3a7))
52
+
53
+ ### ❤️ Contributors
54
+
55
+ - Rrd108 ([@rrd108](https://github.com/rrd108))
56
+
4
57
  ## v1.22.0
5
58
 
6
59
  [compare changes](https://github.com/rrd108/nuxt-users/compare/v1.21.0...v1.22.0)
package/dist/module.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "nuxt-users",
3
3
  "configKey": "nuxtUsers",
4
- "version": "1.22.0",
4
+ "version": "1.23.1",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.2",
7
7
  "unbuild": "3.6.0"
@@ -172,7 +172,7 @@ const handleForgotPassword = async () => {
172
172
  >
173
173
  <div
174
174
  v-if="forgotPasswordMessage"
175
- class="success-message"
175
+ class="n-users-success-message"
176
176
  >
177
177
  {{ forgotPasswordMessage }}
178
178
  </div>
@@ -185,7 +185,7 @@ const handleForgotPassword = async () => {
185
185
  >
186
186
  <div
187
187
  v-if="error"
188
- class="error-message"
188
+ class="n-users-error-message"
189
189
  >
190
190
  {{ error }}
191
191
  </div>
@@ -45,7 +45,7 @@ const handleLogout = async (event) => {
45
45
 
46
46
  <template>
47
47
  <div
48
- :class="['logout-container', props.containerClass]"
48
+ :class="['n-users-logout-container', props.containerClass]"
49
49
  :style="props.containerStyle"
50
50
  >
51
51
  <div
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Composable to get public paths and accessible paths for current user
3
+ * @returns Object containing different categories of accessible paths
4
+ */
5
+ export declare const usePublicPaths: () => {
6
+ getPublicPaths: () => {
7
+ all: any[];
8
+ builtIn: {
9
+ pages: string[];
10
+ api: string[];
11
+ };
12
+ whitelist: any;
13
+ customPasswordResetPath: any;
14
+ apiBasePath: any;
15
+ };
16
+ getAccessiblePaths: () => {
17
+ all: any[];
18
+ public: any[];
19
+ roleBasedPaths: string[];
20
+ userRole: any;
21
+ };
22
+ isPublicPath: (path: string) => boolean;
23
+ isAccessiblePath: (path: string, method?: string) => boolean;
24
+ };
@@ -0,0 +1,114 @@
1
+ import { useRuntimeConfig } from "#app";
2
+ import { NO_AUTH_PATHS, NO_AUTH_API_PATHS } from "../constants.js";
3
+ import { hasPermission, isWhitelisted } from "../utils/permissions.js";
4
+ import { useAuthentication } from "./useAuthentication.js";
5
+ export const usePublicPaths = () => {
6
+ const { public: { nuxtUsers } } = useRuntimeConfig();
7
+ const config = nuxtUsers;
8
+ const apiBasePath = config.apiBasePath || "/api/nuxt-users";
9
+ const { user } = useAuthentication();
10
+ const getPublicPaths = () => {
11
+ const noAuthPaths = [...NO_AUTH_PATHS];
12
+ const noAuthApiPaths = NO_AUTH_API_PATHS.map((path) => `${apiBasePath}${path}`);
13
+ const whitelistedPaths = config.auth?.whitelist || [];
14
+ const customPasswordResetPath = config.passwordResetUrl && config.passwordResetUrl !== "/reset-password" ? config.passwordResetUrl : null;
15
+ const allPublicPaths = [
16
+ ...noAuthPaths,
17
+ ...noAuthApiPaths,
18
+ ...whitelistedPaths
19
+ ];
20
+ if (customPasswordResetPath) {
21
+ allPublicPaths.push(customPasswordResetPath);
22
+ }
23
+ return {
24
+ // All truly public paths (no auth required)
25
+ all: allPublicPaths,
26
+ // Categorized public paths
27
+ builtIn: {
28
+ pages: noAuthPaths,
29
+ api: noAuthApiPaths
30
+ },
31
+ whitelist: whitelistedPaths,
32
+ customPasswordResetPath,
33
+ apiBasePath
34
+ };
35
+ };
36
+ const getAccessiblePaths = () => {
37
+ const publicPaths = getPublicPaths();
38
+ if (!user.value) {
39
+ return {
40
+ all: publicPaths.all,
41
+ public: publicPaths.all,
42
+ roleBasedPaths: [],
43
+ userRole: null
44
+ };
45
+ }
46
+ const userRole = user.value.role;
47
+ const permissions = config.auth?.permissions || {};
48
+ const rolePermissions = permissions[userRole] || [];
49
+ const roleBasedPaths = [];
50
+ rolePermissions.forEach((permission) => {
51
+ if (typeof permission === "string") {
52
+ roleBasedPaths.push(permission);
53
+ } else if (typeof permission === "object" && permission.path) {
54
+ roleBasedPaths.push(permission.path);
55
+ }
56
+ });
57
+ return {
58
+ all: [...publicPaths.all, ...roleBasedPaths],
59
+ public: publicPaths.all,
60
+ roleBasedPaths,
61
+ userRole
62
+ };
63
+ };
64
+ const isAccessiblePath = (path, method = "GET") => {
65
+ if (path.includes(".")) {
66
+ return true;
67
+ }
68
+ if (path.startsWith("/_")) {
69
+ return true;
70
+ }
71
+ if (NO_AUTH_PATHS.includes(path)) {
72
+ return true;
73
+ }
74
+ const noAuthApiPaths = NO_AUTH_API_PATHS.map((p) => `${apiBasePath}${p}`);
75
+ if (noAuthApiPaths.includes(path)) {
76
+ return true;
77
+ }
78
+ if (config.passwordResetUrl && config.passwordResetUrl !== "/reset-password" && path === config.passwordResetUrl) {
79
+ return true;
80
+ }
81
+ if (isWhitelisted(path, config.auth?.whitelist || [])) {
82
+ return true;
83
+ }
84
+ if (user.value) {
85
+ return hasPermission(user.value.role, path, method, config.auth?.permissions || {});
86
+ }
87
+ return false;
88
+ };
89
+ const isPublicPath = (path) => {
90
+ if (path.includes(".")) {
91
+ return true;
92
+ }
93
+ if (path.startsWith("/_")) {
94
+ return true;
95
+ }
96
+ if (NO_AUTH_PATHS.includes(path)) {
97
+ return true;
98
+ }
99
+ const noAuthApiPaths = NO_AUTH_API_PATHS.map((p) => `${apiBasePath}${p}`);
100
+ if (noAuthApiPaths.includes(path)) {
101
+ return true;
102
+ }
103
+ if (config.passwordResetUrl && config.passwordResetUrl !== "/reset-password" && path === config.passwordResetUrl) {
104
+ return true;
105
+ }
106
+ return isWhitelisted(path, config.auth?.whitelist || []);
107
+ };
108
+ return {
109
+ getPublicPaths,
110
+ getAccessiblePaths,
111
+ isPublicPath,
112
+ isAccessiblePath
113
+ };
114
+ };
@@ -72,28 +72,21 @@ export const updateUser = async (id, userData, options) => {
72
72
  const db = await useDb(options);
73
73
  const usersTable = options.tables.users;
74
74
  const allowedFields = ["name", "email", "role", "active"];
75
- const updates = [];
76
- const values = [];
77
- for (const field of allowedFields) {
78
- if (userData[field] !== void 0) {
79
- updates.push(`${field} = ?`);
80
- values.push(userData[field]);
81
- }
82
- }
83
- if (userData.active === false) {
84
- await revokeUserTokens(id, options);
85
- }
86
- if (updates.length === 0) {
75
+ const fieldsToUpdate = allowedFields.filter((field) => userData[field] !== void 0);
76
+ if (fieldsToUpdate.length === 0) {
87
77
  const currentUser = await findUserById(id, options);
88
78
  if (!currentUser) {
89
79
  throw new Error("User not found.");
90
80
  }
91
81
  return currentUser;
92
82
  }
93
- updates.push("updated_at = CURRENT_TIMESTAMP");
94
- values.push(id);
95
- const setClause = updates.map((update) => update.replace(" = ?", "")).join(", ");
96
- await db.sql`UPDATE {${usersTable}} SET {${setClause}} WHERE id = ${id}`;
83
+ if (userData.active === false) {
84
+ await revokeUserTokens(id, options);
85
+ }
86
+ for (const field of fieldsToUpdate) {
87
+ await db.sql`UPDATE {${usersTable}} SET {${field}} = ${userData[field]} WHERE id = ${id}`;
88
+ }
89
+ await db.sql`UPDATE {${usersTable}} SET updated_at = CURRENT_TIMESTAMP WHERE id = ${id}`;
97
90
  const updatedUser = await findUserById(id, options);
98
91
  if (!updatedUser) {
99
92
  throw new Error("Failed to retrieve updated user.");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nuxt-users",
3
- "version": "1.22.0",
3
+ "version": "1.23.1",
4
4
  "description": "A comprehensive user management module for Nuxt 3 and Nuxt 4 applications with authentication, authorization, database support, and CLI tools",
5
5
  "keywords": [
6
6
  "nuxt",
@@ -66,6 +66,7 @@
66
66
  "lint": "eslint .",
67
67
  "lint:fix": "eslint . --fix",
68
68
  "pretest": "node -v | grep -q 'v22' || (echo 'Please use Node.js v22 for testing' && exit 1)",
69
+ "test:release": "yarn test:types && yarn test:unit && yarn test:sqlite && yarn build && yarn lint:fix",
69
70
  "test:types": "yarn dev:prepare && vue-tsc --noEmit && cd playground && vue-tsc --noEmit",
70
71
  "test:unit": "./scripts/test-unit.sh",
71
72
  "test:sqlite": "./scripts/test-sqlite.sh",