nuxt-users 1.34.1 → 1.34.2

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,30 @@
1
1
  # Changelog
2
2
 
3
3
 
4
+ ## v1.34.2
5
+
6
+ [compare changes](https://github.com/rrd108/nuxt-users/compare/v1.34.1...v1.34.2)
7
+
8
+ ### 🩹 Fixes
9
+
10
+ - Remember me closes #3 ([#3](https://github.com/rrd108/nuxt-users/issues/3))
11
+
12
+ ### 💅 Refactors
13
+
14
+ - Component imports ([5b18736](https://github.com/rrd108/nuxt-users/commit/5b18736))
15
+
16
+ ### 📖 Documentation
17
+
18
+ - Add getCurrentUser ([bc30658](https://github.com/rrd108/nuxt-users/commit/bc30658))
19
+
20
+ ### 🏡 Chore
21
+
22
+ - **release:** V1.34.1 ([a335bfc](https://github.com/rrd108/nuxt-users/commit/a335bfc))
23
+
24
+ ### ❤️ Contributors
25
+
26
+ - Rrd108 ([@rrd108](https://github.com/rrd108))
27
+
4
28
  ## v1.34.1
5
29
 
6
30
  [compare changes](https://github.com/rrd108/nuxt-users/compare/v1.34.0...v1.34.1)
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.BOm7L39P.mjs';
2
+ import { R as RuntimeModuleOptions, M as ModuleOptions } from './shared/nuxt-users.BTVH9EyH.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.BOm7L39P.js';
2
+ import { R as RuntimeModuleOptions, M as ModuleOptions } from './shared/nuxt-users.BTVH9EyH.js';
3
3
  export * from '../dist/runtime/server/internal/index.js';
4
4
 
5
5
  declare const defaultOptions: ModuleOptions;
package/dist/module.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "nuxt-users",
3
3
  "configKey": "nuxtUsers",
4
- "version": "1.34.1",
4
+ "version": "1.34.2",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.2",
7
7
  "unbuild": "3.6.0"
package/dist/module.mjs CHANGED
@@ -36,7 +36,9 @@ const defaultOptions = {
36
36
  auth: {
37
37
  whitelist: [],
38
38
  tokenExpiration: 24 * 60,
39
- // 24 hours
39
+ // 24 hours in minutes
40
+ rememberMeExpiration: 30,
41
+ // 30 days
40
42
  permissions: {}
41
43
  // Empty by default - whitelist approach
42
44
  },
@@ -30,10 +30,11 @@ const handleSubmit = async () => {
30
30
  method: "POST",
31
31
  body: {
32
32
  email: formData.value.email,
33
- password: formData.value.password
33
+ password: formData.value.password,
34
+ rememberMe: formData.value.rememberMe
34
35
  }
35
36
  });
36
- emit("success", response.user);
37
+ emit("success", response.user, formData.value.rememberMe ?? false);
37
38
  if (props.redirectTo) {
38
39
  await navigateTo(props.redirectTo);
39
40
  }
@@ -26,13 +26,13 @@ type __VLS_Slots = {} & {
26
26
  'error-message'?: (props: typeof __VLS_15) => any;
27
27
  };
28
28
  declare const __VLS_component: import("vue").DefineComponent<Props, void, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
29
- success: (user: UserWithoutPassword) => any;
29
+ success: (user: UserWithoutPassword, rememberMe: boolean) => any;
30
30
  error: (error: string) => any;
31
31
  submit: (data: LoginFormData) => any;
32
32
  "forgot-password-error": (error: string) => any;
33
33
  "forgot-password-success": () => any;
34
34
  }, string, import("vue").PublicProps, Readonly<Props> & Readonly<{
35
- onSuccess?: ((user: UserWithoutPassword) => any) | undefined;
35
+ onSuccess?: ((user: UserWithoutPassword, rememberMe: boolean) => any) | undefined;
36
36
  onError?: ((error: string) => any) | undefined;
37
37
  onSubmit?: ((data: LoginFormData) => any) | undefined;
38
38
  "onForgot-password-error"?: ((error: string) => any) | undefined;
@@ -2,7 +2,7 @@ import type { User } from 'nuxt-users/utils';
2
2
  export declare const useAuthentication: () => {
3
3
  user: Readonly<import("vue").Ref<any, any>>;
4
4
  isAuthenticated: import("vue").ComputedRef<boolean>;
5
- login: (userData: User) => void;
5
+ login: (userData: User, rememberMe?: boolean) => void;
6
6
  logout: () => Promise<void>;
7
7
  fetchUser: () => Promise<any>;
8
8
  initializeUser: () => Promise<void>;
@@ -1,15 +1,22 @@
1
1
  import { useState, useRuntimeConfig } from "#app";
2
2
  import { computed, readonly } from "vue";
3
+ let initializationPromise = null;
3
4
  export const useAuthentication = () => {
4
5
  const user = useState("user", () => null);
5
6
  const { public: { nuxtUsers } } = useRuntimeConfig();
6
7
  const apiBasePath = nuxtUsers?.apiBasePath;
7
8
  const isAuthenticated = computed(() => !!user.value);
8
- const login = (userData) => {
9
+ const login = (userData, rememberMe = false) => {
9
10
  const { password: _, ...userWithoutPassword } = userData;
10
11
  user.value = userWithoutPassword;
11
12
  if (import.meta.client) {
12
- localStorage.setItem("user", JSON.stringify(userWithoutPassword));
13
+ localStorage.removeItem("user");
14
+ sessionStorage.removeItem("user");
15
+ if (rememberMe) {
16
+ localStorage.setItem("user", JSON.stringify(userWithoutPassword));
17
+ } else {
18
+ sessionStorage.setItem("user", JSON.stringify(userWithoutPassword));
19
+ }
13
20
  }
14
21
  };
15
22
  const logout = async () => {
@@ -18,10 +25,15 @@ export const useAuthentication = () => {
18
25
  user.value = null;
19
26
  if (import.meta.client) {
20
27
  localStorage.removeItem("user");
28
+ sessionStorage.removeItem("user");
21
29
  }
22
30
  } catch (error) {
23
31
  console.error("Logout failed:", error);
24
32
  user.value = null;
33
+ if (import.meta.client) {
34
+ localStorage.removeItem("user");
35
+ sessionStorage.removeItem("user");
36
+ }
25
37
  }
26
38
  };
27
39
  const fetchUser = async () => {
@@ -29,7 +41,15 @@ export const useAuthentication = () => {
29
41
  const response = await $fetch(`${apiBasePath}/me`, { method: "GET" });
30
42
  user.value = response.user;
31
43
  if (import.meta.client) {
32
- localStorage.setItem("user", JSON.stringify(response.user));
44
+ const wasInLocalStorage = localStorage.getItem("user") !== null;
45
+ const wasInSessionStorage = sessionStorage.getItem("user") !== null;
46
+ if (wasInLocalStorage) {
47
+ localStorage.setItem("user", JSON.stringify(response.user));
48
+ } else if (wasInSessionStorage) {
49
+ sessionStorage.setItem("user", JSON.stringify(response.user));
50
+ } else {
51
+ sessionStorage.setItem("user", JSON.stringify(response.user));
52
+ }
33
53
  }
34
54
  return response.user;
35
55
  } catch (error) {
@@ -37,6 +57,7 @@ export const useAuthentication = () => {
37
57
  user.value = null;
38
58
  if (import.meta.client) {
39
59
  localStorage.removeItem("user");
60
+ sessionStorage.removeItem("user");
40
61
  }
41
62
  return null;
42
63
  }
@@ -45,7 +66,9 @@ export const useAuthentication = () => {
45
66
  if (!import.meta.client) {
46
67
  return;
47
68
  }
48
- const storedUser = localStorage.getItem("user");
69
+ const storedUserLocal = localStorage.getItem("user");
70
+ const storedUserSession = sessionStorage.getItem("user");
71
+ const storedUser = storedUserLocal || storedUserSession;
49
72
  if (storedUser) {
50
73
  try {
51
74
  user.value = JSON.parse(storedUser);
@@ -53,10 +76,15 @@ export const useAuthentication = () => {
53
76
  } catch (error) {
54
77
  console.error("Failed to parse stored user:", error);
55
78
  localStorage.removeItem("user");
79
+ sessionStorage.removeItem("user");
56
80
  user.value = null;
57
81
  }
58
82
  }
59
83
  };
84
+ if (import.meta.client && !initializationPromise) {
85
+ initializationPromise = initializeUser().catch(() => {
86
+ });
87
+ }
60
88
  return {
61
89
  user: readonly(user),
62
90
  isAuthenticated,
@@ -5,7 +5,7 @@ import { useRuntimeConfig } from "#imports";
5
5
  import { useDb } from "../../../utils/db.js";
6
6
  export default defineEventHandler(async (event) => {
7
7
  const body = await readBody(event);
8
- const { email, password } = body;
8
+ const { email, password, rememberMe } = body;
9
9
  if (!email || !password) {
10
10
  throw createError({
11
11
  statusCode: 400,
@@ -42,21 +42,30 @@ export default defineEventHandler(async (event) => {
42
42
  const token = crypto.randomBytes(64).toString("hex");
43
43
  const tokenName = "auth_token";
44
44
  const expiresAt = /* @__PURE__ */ new Date();
45
- expiresAt.setMinutes(expiresAt.getMinutes() + options.auth.tokenExpiration);
45
+ if (rememberMe) {
46
+ const longTermDays = options.auth.rememberMeExpiration || 30;
47
+ expiresAt.setDate(expiresAt.getDate() + longTermDays);
48
+ } else {
49
+ expiresAt.setMinutes(expiresAt.getMinutes() + options.auth.tokenExpiration);
50
+ }
46
51
  await db.sql`
47
52
  INSERT INTO {${personalAccessTokensTable}} (tokenable_type, tokenable_id, name, token, expires_at, created_at, updated_at)
48
53
  VALUES ('user', ${user.id}, ${tokenName}, ${token}, ${expiresAt.toISOString().slice(0, 19).replace("T", " ")}, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)
49
54
  `;
50
- setCookie(event, "auth_token", token, {
55
+ const cookieOptions = {
51
56
  httpOnly: true,
52
57
  secure: process.env.NODE_ENV === "production",
53
58
  // Use secure cookies in production
54
59
  sameSite: "lax",
55
60
  // Adjust as needed
56
- maxAge: 60 * 60 * 24 * 7,
57
- // 7 days
58
61
  path: "/"
59
- });
62
+ };
63
+ if (rememberMe) {
64
+ const longTermDays = options.auth.rememberMeExpiration || 30;
65
+ cookieOptions.maxAge = 60 * 60 * 24 * longTermDays;
66
+ } else {
67
+ }
68
+ setCookie(event, "auth_token", token, cookieOptions);
60
69
  const { password: _, ...userWithoutPassword } = user;
61
70
  return { user: userWithoutPassword };
62
71
  });
@@ -60,6 +60,11 @@ interface RuntimeModuleOptions {
60
60
  * @default 1440
61
61
  */
62
62
  tokenExpiration?: number;
63
+ /**
64
+ * Remember me token expiration time in days
65
+ * @default 30
66
+ */
67
+ rememberMeExpiration?: number;
63
68
  /**
64
69
  * Role-based permissions configuration
65
70
  * @default {}
@@ -132,6 +137,7 @@ interface ModuleOptions {
132
137
  auth: {
133
138
  whitelist: string[];
134
139
  tokenExpiration: number;
140
+ rememberMeExpiration: number;
135
141
  permissions: Record<string, (string | Permission)[]>;
136
142
  };
137
143
  passwordValidation: {
@@ -60,6 +60,11 @@ interface RuntimeModuleOptions {
60
60
  * @default 1440
61
61
  */
62
62
  tokenExpiration?: number;
63
+ /**
64
+ * Remember me token expiration time in days
65
+ * @default 30
66
+ */
67
+ rememberMeExpiration?: number;
63
68
  /**
64
69
  * Role-based permissions configuration
65
70
  * @default {}
@@ -132,6 +137,7 @@ interface ModuleOptions {
132
137
  auth: {
133
138
  whitelist: string[];
134
139
  tokenExpiration: number;
140
+ rememberMeExpiration: number;
135
141
  permissions: Record<string, (string | Permission)[]>;
136
142
  };
137
143
  passwordValidation: {
package/dist/utils.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- export { g as DatabaseConfig, f as DatabaseType, D as DisplayFieldsProps, L as LoginFormData, c as LoginFormProps, M as ModuleOptions, b as PasswordResetToken, e as Permission, P as PersonalAccessToken, d as ResetPasswordFormProps, R as RuntimeModuleOptions, U as User, a as UserWithoutPassword, h as defaultDisplayFields, i as defaultFieldLabels } from './shared/nuxt-users.BOm7L39P.mjs';
1
+ export { g as DatabaseConfig, f as DatabaseType, D as DisplayFieldsProps, L as LoginFormData, c as LoginFormProps, M as ModuleOptions, b as PasswordResetToken, e as Permission, P as PersonalAccessToken, d as ResetPasswordFormProps, R as RuntimeModuleOptions, U as User, a as UserWithoutPassword, h as defaultDisplayFields, i as defaultFieldLabels } from './shared/nuxt-users.BTVH9EyH.mjs';
2
2
 
3
3
  interface PasswordValidationResult {
4
4
  isValid: boolean;
package/dist/utils.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { g as DatabaseConfig, f as DatabaseType, D as DisplayFieldsProps, L as LoginFormData, c as LoginFormProps, M as ModuleOptions, b as PasswordResetToken, e as Permission, P as PersonalAccessToken, d as ResetPasswordFormProps, R as RuntimeModuleOptions, U as User, a as UserWithoutPassword, h as defaultDisplayFields, i as defaultFieldLabels } from './shared/nuxt-users.BOm7L39P.js';
1
+ export { g as DatabaseConfig, f as DatabaseType, D as DisplayFieldsProps, L as LoginFormData, c as LoginFormProps, M as ModuleOptions, b as PasswordResetToken, e as Permission, P as PersonalAccessToken, d as ResetPasswordFormProps, R as RuntimeModuleOptions, U as User, a as UserWithoutPassword, h as defaultDisplayFields, i as defaultFieldLabels } from './shared/nuxt-users.BTVH9EyH.js';
2
2
 
3
3
  interface PasswordValidationResult {
4
4
  isValid: boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nuxt-users",
3
- "version": "1.34.1",
3
+ "version": "1.34.2",
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",