@wpnuxt/auth 2.0.0-alpha.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/dist/module.d.mts +7 -0
- package/dist/module.json +9 -0
- package/dist/module.mjs +46 -0
- package/dist/runtime/composables/useWPAuth.d.ts +0 -0
- package/dist/runtime/composables/useWPAuth.js +103 -0
- package/dist/runtime/composables/useWPUser.d.ts +0 -0
- package/dist/runtime/composables/useWPUser.js +66 -0
- package/dist/runtime/plugins/auth.d.ts +0 -0
- package/dist/runtime/plugins/auth.js +19 -0
- package/dist/runtime/queries/Auth.gql +31 -0
- package/dist/runtime/types/graphql-middleware.d.ts +21 -0
- package/dist/runtime/types/index.d.ts +0 -0
- package/dist/runtime/types/index.js +0 -0
- package/dist/types.d.mts +9 -0
- package/package.json +56 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import * as _nuxt_schema from '@nuxt/schema';
|
|
2
|
+
import { WPNuxtAuthConfig } from '../dist/runtime/types/index.js';
|
|
3
|
+
export { WPNuxtAuthConfig } from '../dist/runtime/types/index.js';
|
|
4
|
+
|
|
5
|
+
declare const _default: _nuxt_schema.NuxtModule<WPNuxtAuthConfig, WPNuxtAuthConfig, false>;
|
|
6
|
+
|
|
7
|
+
export { _default as default };
|
package/dist/module.json
ADDED
package/dist/module.mjs
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { defineNuxtModule, createResolver, addPlugin, addImports } from '@nuxt/kit';
|
|
2
|
+
|
|
3
|
+
const module$1 = defineNuxtModule({
|
|
4
|
+
meta: {
|
|
5
|
+
name: "@wpnuxt/auth",
|
|
6
|
+
configKey: "wpNuxtAuth"
|
|
7
|
+
},
|
|
8
|
+
defaults: {
|
|
9
|
+
enabled: true,
|
|
10
|
+
cookieName: "wpnuxt-auth-token",
|
|
11
|
+
refreshCookieName: "wpnuxt-refresh-token",
|
|
12
|
+
tokenMaxAge: 3600,
|
|
13
|
+
refreshTokenMaxAge: 604800,
|
|
14
|
+
redirectOnLogin: "/",
|
|
15
|
+
redirectOnLogout: "/",
|
|
16
|
+
loginPage: "/login"
|
|
17
|
+
},
|
|
18
|
+
async setup(options, nuxt) {
|
|
19
|
+
if (!options.enabled) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
const resolver = createResolver(import.meta.url);
|
|
23
|
+
nuxt.options.runtimeConfig.public.wpNuxtAuth = {
|
|
24
|
+
cookieName: options.cookieName,
|
|
25
|
+
refreshCookieName: options.refreshCookieName,
|
|
26
|
+
tokenMaxAge: options.tokenMaxAge,
|
|
27
|
+
refreshTokenMaxAge: options.refreshTokenMaxAge,
|
|
28
|
+
redirectOnLogin: options.redirectOnLogin,
|
|
29
|
+
redirectOnLogout: options.redirectOnLogout,
|
|
30
|
+
loginPage: options.loginPage
|
|
31
|
+
};
|
|
32
|
+
addPlugin(resolver.resolve("./runtime/plugins/auth"));
|
|
33
|
+
addImports([
|
|
34
|
+
{ name: "useWPAuth", from: resolver.resolve("./runtime/composables/useWPAuth") },
|
|
35
|
+
{ name: "useWPUser", from: resolver.resolve("./runtime/composables/useWPUser") }
|
|
36
|
+
]);
|
|
37
|
+
nuxt.hook("prepare:types", ({ references }) => {
|
|
38
|
+
references.push({
|
|
39
|
+
path: resolver.resolve("./runtime/types/index.ts")
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
console.log("[WPNuxt Auth] Module loaded");
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
export { module$1 as default };
|
|
File without changes
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { computed, useState, useCookie, useRuntimeConfig, navigateTo, useGraphqlMutation } from "#imports";
|
|
2
|
+
export function useWPAuth() {
|
|
3
|
+
const config = useRuntimeConfig().public.wpNuxtAuth;
|
|
4
|
+
const authState = useState("wpnuxt-auth", () => ({
|
|
5
|
+
user: null,
|
|
6
|
+
isAuthenticated: false,
|
|
7
|
+
isLoading: false,
|
|
8
|
+
error: null
|
|
9
|
+
}));
|
|
10
|
+
const authToken = useCookie(config.cookieName, {
|
|
11
|
+
maxAge: config.tokenMaxAge,
|
|
12
|
+
secure: process.env.NODE_ENV === "production",
|
|
13
|
+
sameSite: "lax"
|
|
14
|
+
});
|
|
15
|
+
const refreshToken = useCookie(config.refreshCookieName, {
|
|
16
|
+
maxAge: config.refreshTokenMaxAge,
|
|
17
|
+
secure: process.env.NODE_ENV === "production",
|
|
18
|
+
sameSite: "lax"
|
|
19
|
+
});
|
|
20
|
+
async function login(credentials) {
|
|
21
|
+
authState.value.isLoading = true;
|
|
22
|
+
authState.value.error = null;
|
|
23
|
+
try {
|
|
24
|
+
const { data, errors } = await useGraphqlMutation("Login", {
|
|
25
|
+
username: credentials.username,
|
|
26
|
+
password: credentials.password
|
|
27
|
+
});
|
|
28
|
+
if (errors?.length) {
|
|
29
|
+
const errorMessage = errors[0]?.message || "Login failed";
|
|
30
|
+
authState.value.error = errorMessage;
|
|
31
|
+
authState.value.isLoading = false;
|
|
32
|
+
return { success: false, error: errorMessage };
|
|
33
|
+
}
|
|
34
|
+
if (data?.login) {
|
|
35
|
+
authToken.value = data.login.authToken;
|
|
36
|
+
refreshToken.value = data.login.refreshToken;
|
|
37
|
+
authState.value.user = data.login.user;
|
|
38
|
+
authState.value.isAuthenticated = true;
|
|
39
|
+
authState.value.isLoading = false;
|
|
40
|
+
return {
|
|
41
|
+
success: true,
|
|
42
|
+
user: data.login.user,
|
|
43
|
+
tokens: {
|
|
44
|
+
authToken: data.login.authToken,
|
|
45
|
+
refreshToken: data.login.refreshToken
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
authState.value.isLoading = false;
|
|
50
|
+
return { success: false, error: "Invalid response from server" };
|
|
51
|
+
} catch (error) {
|
|
52
|
+
const errorMessage = error instanceof Error ? error.message : "Login failed";
|
|
53
|
+
authState.value.error = errorMessage;
|
|
54
|
+
authState.value.isLoading = false;
|
|
55
|
+
return { success: false, error: errorMessage };
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
async function logout() {
|
|
59
|
+
authToken.value = null;
|
|
60
|
+
refreshToken.value = null;
|
|
61
|
+
authState.value.user = null;
|
|
62
|
+
authState.value.isAuthenticated = false;
|
|
63
|
+
authState.value.error = null;
|
|
64
|
+
if (config.redirectOnLogout) {
|
|
65
|
+
await navigateTo(config.redirectOnLogout);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
async function refresh() {
|
|
69
|
+
if (!refreshToken.value) {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
try {
|
|
73
|
+
const { data, errors } = await useGraphqlMutation("RefreshAuthToken", {
|
|
74
|
+
refreshToken: refreshToken.value
|
|
75
|
+
});
|
|
76
|
+
if (errors?.length || !data?.refreshJwtAuthToken) {
|
|
77
|
+
await logout();
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
authToken.value = data.refreshJwtAuthToken.authToken;
|
|
81
|
+
return true;
|
|
82
|
+
} catch {
|
|
83
|
+
await logout();
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
function getToken() {
|
|
88
|
+
return authToken.value || null;
|
|
89
|
+
}
|
|
90
|
+
return {
|
|
91
|
+
// State
|
|
92
|
+
state: authState,
|
|
93
|
+
user: computed(() => authState.value.user),
|
|
94
|
+
isAuthenticated: computed(() => authState.value.isAuthenticated),
|
|
95
|
+
isLoading: computed(() => authState.value.isLoading),
|
|
96
|
+
error: computed(() => authState.value.error),
|
|
97
|
+
// Methods
|
|
98
|
+
login,
|
|
99
|
+
logout,
|
|
100
|
+
refresh,
|
|
101
|
+
getToken
|
|
102
|
+
};
|
|
103
|
+
}
|
|
File without changes
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { computed, useState, useGraphqlQuery } from "#imports";
|
|
2
|
+
export function useWPUser() {
|
|
3
|
+
const userState = useState("wpnuxt-user", () => null);
|
|
4
|
+
const loadingState = useState("wpnuxt-user-loading", () => false);
|
|
5
|
+
const errorState = useState("wpnuxt-user-error", () => null);
|
|
6
|
+
async function fetchUser() {
|
|
7
|
+
loadingState.value = true;
|
|
8
|
+
errorState.value = null;
|
|
9
|
+
try {
|
|
10
|
+
const { data, errors } = await useGraphqlQuery("Viewer");
|
|
11
|
+
if (errors?.length) {
|
|
12
|
+
errorState.value = errors[0]?.message || "Failed to fetch user";
|
|
13
|
+
loadingState.value = false;
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
userState.value = data?.viewer || null;
|
|
17
|
+
loadingState.value = false;
|
|
18
|
+
return userState.value;
|
|
19
|
+
} catch (error) {
|
|
20
|
+
errorState.value = error instanceof Error ? error.message : "Failed to fetch user";
|
|
21
|
+
loadingState.value = false;
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
function clearUser() {
|
|
26
|
+
userState.value = null;
|
|
27
|
+
errorState.value = null;
|
|
28
|
+
}
|
|
29
|
+
function hasRole(roleName) {
|
|
30
|
+
if (!userState.value?.roles?.nodes) {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
return userState.value.roles.nodes.some(
|
|
34
|
+
(role) => role.name.toLowerCase() === roleName.toLowerCase()
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
function isAdmin() {
|
|
38
|
+
return hasRole("administrator");
|
|
39
|
+
}
|
|
40
|
+
function isEditor() {
|
|
41
|
+
return hasRole("editor") || isAdmin();
|
|
42
|
+
}
|
|
43
|
+
function getDisplayName() {
|
|
44
|
+
if (!userState.value) {
|
|
45
|
+
return "";
|
|
46
|
+
}
|
|
47
|
+
return userState.value.name || `${userState.value.firstName || ""} ${userState.value.lastName || ""}`.trim() || userState.value.username || "";
|
|
48
|
+
}
|
|
49
|
+
function getAvatarUrl() {
|
|
50
|
+
return userState.value?.avatar?.url || null;
|
|
51
|
+
}
|
|
52
|
+
return {
|
|
53
|
+
// State
|
|
54
|
+
user: computed(() => userState.value),
|
|
55
|
+
isLoading: computed(() => loadingState.value),
|
|
56
|
+
error: computed(() => errorState.value),
|
|
57
|
+
// Methods
|
|
58
|
+
fetchUser,
|
|
59
|
+
clearUser,
|
|
60
|
+
hasRole,
|
|
61
|
+
isAdmin,
|
|
62
|
+
isEditor,
|
|
63
|
+
getDisplayName,
|
|
64
|
+
getAvatarUrl
|
|
65
|
+
};
|
|
66
|
+
}
|
|
File without changes
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { defineNuxtPlugin, useCookie, useRuntimeConfig, useState } from "#imports";
|
|
2
|
+
export default defineNuxtPlugin({
|
|
3
|
+
name: "wpnuxt-auth",
|
|
4
|
+
enforce: "pre",
|
|
5
|
+
async setup() {
|
|
6
|
+
const config = useRuntimeConfig().public.wpNuxtAuth;
|
|
7
|
+
const authState = useState("wpnuxt-auth", () => ({
|
|
8
|
+
user: null,
|
|
9
|
+
isAuthenticated: false,
|
|
10
|
+
isLoading: true,
|
|
11
|
+
error: null
|
|
12
|
+
}));
|
|
13
|
+
const authToken = useCookie(config.cookieName);
|
|
14
|
+
if (authToken.value) {
|
|
15
|
+
authState.value.isAuthenticated = true;
|
|
16
|
+
}
|
|
17
|
+
authState.value.isLoading = false;
|
|
18
|
+
}
|
|
19
|
+
});
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Login mutation for WPGraphQL JWT Authentication
|
|
2
|
+
mutation Login($username: String!, $password: String!) {
|
|
3
|
+
login(input: { username: $username, password: $password }) {
|
|
4
|
+
authToken
|
|
5
|
+
refreshToken
|
|
6
|
+
user {
|
|
7
|
+
id
|
|
8
|
+
databaseId
|
|
9
|
+
name
|
|
10
|
+
email
|
|
11
|
+
firstName
|
|
12
|
+
lastName
|
|
13
|
+
username
|
|
14
|
+
avatar {
|
|
15
|
+
url
|
|
16
|
+
}
|
|
17
|
+
roles {
|
|
18
|
+
nodes {
|
|
19
|
+
name
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
# Refresh auth token mutation
|
|
27
|
+
mutation RefreshAuthToken($refreshToken: String!) {
|
|
28
|
+
refreshJwtAuthToken(input: { jwtRefreshToken: $refreshToken }) {
|
|
29
|
+
authToken
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type augmentations for nuxt-graphql-middleware composables
|
|
3
|
+
* These are provided at runtime when @wpnuxt/core is installed
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// Make this a module to enable proper augmentation
|
|
7
|
+
export {}
|
|
8
|
+
|
|
9
|
+
declare module '#imports' {
|
|
10
|
+
export function useGraphqlQuery<T = unknown>(
|
|
11
|
+
operationName: string,
|
|
12
|
+
variables?: Record<string, unknown>,
|
|
13
|
+
options?: Record<string, unknown>
|
|
14
|
+
): Promise<{ data: T | null, errors?: Array<{ message: string }> }>
|
|
15
|
+
|
|
16
|
+
export function useGraphqlMutation<T = unknown>(
|
|
17
|
+
operationName: string,
|
|
18
|
+
variables?: Record<string, unknown>,
|
|
19
|
+
options?: Record<string, unknown>
|
|
20
|
+
): Promise<{ data: T | null, errors?: Array<{ message: string }> }>
|
|
21
|
+
}
|
|
File without changes
|
|
File without changes
|
package/dist/types.d.mts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { NuxtModule } from '@nuxt/schema'
|
|
2
|
+
|
|
3
|
+
import type { default as Module } from './module.mjs'
|
|
4
|
+
|
|
5
|
+
export type ModuleOptions = typeof Module extends NuxtModule<infer O> ? Partial<O> : Record<string, any>
|
|
6
|
+
|
|
7
|
+
export { type WPNuxtAuthConfig } from '../dist/runtime/types/index.js'
|
|
8
|
+
|
|
9
|
+
export { default } from './module.mjs'
|
package/package.json
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@wpnuxt/auth",
|
|
3
|
+
"version": "2.0.0-alpha.1",
|
|
4
|
+
"description": "Authentication module for WPNuxt using WPGraphQL JWT",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"nuxt",
|
|
7
|
+
"nuxt-module",
|
|
8
|
+
"wordpress",
|
|
9
|
+
"authentication",
|
|
10
|
+
"jwt",
|
|
11
|
+
"wpgraphql",
|
|
12
|
+
"vue",
|
|
13
|
+
"typescript"
|
|
14
|
+
],
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "git+https://github.com/wpnuxt/wpnuxt.git",
|
|
18
|
+
"directory": "packages/auth"
|
|
19
|
+
},
|
|
20
|
+
"license": "MIT",
|
|
21
|
+
"type": "module",
|
|
22
|
+
"exports": {
|
|
23
|
+
".": {
|
|
24
|
+
"types": "./dist/types.d.mts",
|
|
25
|
+
"import": "./dist/module.mjs"
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
"main": "./dist/module.mjs",
|
|
29
|
+
"types": "./dist/types.d.mts",
|
|
30
|
+
"files": [
|
|
31
|
+
"dist"
|
|
32
|
+
],
|
|
33
|
+
"publishConfig": {
|
|
34
|
+
"access": "public"
|
|
35
|
+
},
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"@nuxt/kit": "4.2.2"
|
|
38
|
+
},
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"@nuxt/module-builder": "^1.0.2",
|
|
41
|
+
"@nuxt/schema": "4.2.2",
|
|
42
|
+
"@types/node": "^25.0.3",
|
|
43
|
+
"nuxt": "4.2.2",
|
|
44
|
+
"vue-tsc": "^3.2.1"
|
|
45
|
+
},
|
|
46
|
+
"peerDependencies": {
|
|
47
|
+
"nuxt": "^4.0.0",
|
|
48
|
+
"@wpnuxt/core": "2.0.0-alpha.1"
|
|
49
|
+
},
|
|
50
|
+
"scripts": {
|
|
51
|
+
"build": "nuxt-module-build build",
|
|
52
|
+
"dev:prepare": "nuxt-module-build build --stub && nuxt-module-build prepare",
|
|
53
|
+
"typecheck": "vue-tsc --noEmit",
|
|
54
|
+
"clean": "rm -rf dist .nuxt node_modules"
|
|
55
|
+
}
|
|
56
|
+
}
|