gpt4 book ai didi

next.js - 使用 Apollo SubscriptionClient 的动态 Hasura X-Hasura-Role

转载 作者:行者123 更新时间:2023-12-04 02:32:59 31 4
gpt4 key购买 nike

根据 Hasura 中的用户角色动态更改 Apollo SubscriptionClient 中的 header 的正确方法是什么?
堆:

  • 下一篇JS
  • 阿波罗
  • Auth0
  • Hasura(使用角色列存储 Auth0_Id)

  • 这里的目标是利用 Hasura 角色获取权限。我知道 JWT token 具有允许的角色,但我希望能够根据用户分配的角色设置角色。我要走的路径是通过 NextJS 内部 API 使用来自 auth0 的 userID 查询 Hasura 用户表中的角色。
    ApolloClient.js
    import fetch from 'isomorphic-unfetch'
    import { ApolloClient } from 'apollo-client'
    import { InMemoryCache } from 'apollo-cache-inmemory'
    import { HttpLink } from 'apollo-link-http'
    import { onError } from 'apollo-link-error'
    import { WebSocketLink } from 'apollo-link-ws'
    import { SubscriptionClient } from 'subscriptions-transport-ws'

    let accessToken, role, user = null
    const requestAccessToken = async () => {
    if (accessToken) return
    const res = await fetch(`${process.env.NEXT_PUBLIC_POST_LOGOUT_REDIRECT_URI}/api/session`)
    if (res.ok) {
    const json = await res.json()
    accessToken = json.accessToken
    } else {
    accessToken = 'public'
    }
    }

    const requestRole = async (userId) => {
    if (role) return
    const res = await fetch(`${process.env.NEXT_PUBLIC_APP_HOST}/api/role/"${userId}"`)
    if (res.ok) {
    const json = await res.json()
    console.log(json)
    role = json.data.vknursery_users_by_pk.role
    }
    }

    const requestUser = async () => {
    if (role) return
    const res = await fetch(`${process.env.NEXT_PUBLIC_APP_HOST}/api/me`)
    if (res.ok) {
    const json = await res.json()
    user = json
    }
    }
    // remove cached token on 401 from the server
    const resetTokenLink = onError(({ networkError }) => {
    if (networkError && networkError.name === 'ServerError' && networkError.statusCode === 401) {
    accessToken = null
    }
    })
    const createHttpLink = (headers) => {
    const httpLink = new HttpLink({
    uri: `https://${process.env.NEXT_PUBLIC_API_BASE_URL}/v1/graphql`,
    credentials: 'include',
    headers, // auth token is fetched on the server side
    fetch,
    })
    return httpLink;
    }
    const createWSLink = () => {
    return new WebSocketLink(
    new SubscriptionClient(`wss://${process.env.NEXT_PUBLIC_API_BASE_URL}/v1/graphql`, {
    lazy: true,
    reconnect: true,
    connectionParams: async () => {
    await requestAccessToken() // happens on the client
    await requestUser()
    await requestRole(user.sub) //get role from hasura to assign in apollo request headers
    return {
    headers: {
    'X-Hasura-Role': role,
    authorization: accessToken ? `Bearer ${accessToken}` : '',
    },
    }
    },
    })
    )
    }
    export default function createApolloClient(initialState, headers) {
    const ssrMode = typeof window === 'undefined'
    let link

    if (ssrMode) {
    link = createHttpLink(headers) // executed on server
    } else {
    link = createWSLink() // executed on client
    }
    return new ApolloClient({
    ssrMode,
    link,
    cache: new InMemoryCache().restore(initialState),
    })
    }
    /api/role/[userId].js
    import fetch from 'isomorphic-unfetch';

    export default async function me(req, res) {
    const {
    query: { userId },
    } = req
    try {
    await fetch(`https://${process.env.NEXT_PUBLIC_API_BASE_URL}/v1/graphql`, {
    method: 'POST',
    headers: {
    'x-hasura-admin-secret': process.env.HASURA_GRAPHQL_ADMIN_SECRET,
    'Content-Type': 'application/json'
    },
    body: JSON.stringify({ query: `{ vknursery_users_by_pk( auth0_id:${userId}){ role } }` })
    })
    .then(r => r.json())
    .then(data => {
    res.statusCode = 200
    res.setHeader('Content-Type', 'application/json')
    console.log(JSON.stringify(data));
    res.end(JSON.stringify(data))
    });
    } catch (error) {
    console.error(error)
    res.status(error.status || 500).end(error.message)
    }
    }

    /api/me.js
    import auth0 from '../../lib/auth0'

    export default async function me(req, res) {
    try {
    await auth0.handleProfile(req, res)
    } catch (error) {
    console.error(error)
    res.status(error.status || 500).end(error.message)
    }
    }

    最佳答案

    该角色作为与用户表的连接(您可以在此处保留 auth0 id)或作为 由 auth0 签署的 JWT 的一部分 (其 UI 中有角色功能)或 作为身份验证 Hook 的一部分 (参见 Hasura 的文档)。调用客户端不提供角色,因为通常您无法控制其执行。

    关于next.js - 使用 Apollo SubscriptionClient 的动态 Hasura X-Hasura-Role,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63121013/

    31 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com