首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >动态Hasura X-Hasura-与阿波罗SubscriptionClient的角色

动态Hasura X-Hasura-与阿波罗SubscriptionClient的角色
EN

Stack Overflow用户
提问于 2020-07-27 18:02:19
回答 1查看 672关注 0票数 4

根据Hasura中的用户角色动态更改阿波罗SubscriptionClient中的标头的正确方法是什么?

堆叠:

  • NextJS
  • Apollo
  • Auth0
  • Hasura (Stores Auth0_Id with Role列)

这里的目标是利用Hasura角色作为权限。我知道JWT令牌有允许的角色,但我希望能够根据用户分配的角色来设置角色。我要走的路径是通过userID内部API从auth0查询Hasura用户表中的角色。

ApolloClient.js

代码语言:javascript
复制
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

代码语言:javascript
复制
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

代码语言:javascript
复制
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)
  }
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-08-04 21:49:53

该角色可以作为与users表的联接(您可以在这里保留auth0 id ),也可以作为由auth0签名的JWT的部分(其UI中有一个角色特性),或者作为身份验证挂钩的一部分(参见Hasura的文档)。角色不是由调用客户端指定的,因为通常您并不控制它的执行。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63121013

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档