Skip to content

Instantly share code, notes, and snippets.

@runeb
Created April 24, 2023 22:04
Show Gist options
  • Save runeb/90b25608d91c5e1c1c18eb0c2a68e3ce to your computer and use it in GitHub Desktop.
Save runeb/90b25608d91c5e1c1c18eb0c2a68e3ce to your computer and use it in GitHub Desktop.
Example useHasDocumentPermissionInDataset hook for evaluating grants and permissions in configurable dataset
import React from 'react'
import {useHasDocumentPermissionInDataset} from './useHasDocumentPermissionInDataset'
export function MyReactComponent() {
const targetDataset = 'playground'
const hasGrant = useHasDocumentPermissionInDataset({
dataset: targetDataset,
permission: 'update',
documentStub: {_type: 'provide-me', _id: 'provide-me'},
})
let canUpdate = 'Determining...'
if (hasGrant !== null) {
canUpdate = hasGrant ? 'Yep' : 'Nope'
}
return (
<p>
Could I update this document in the "{targetDataset}" dataset? {canUpdate}
</p>
)
}
import {useEffect, useMemo, useState} from 'react'
import {type DocumentValuePermission, createGrantsStore, useClient, useCurrentUser} from 'sanity'
/**
* Used as the fallback document to check grants against.
* For simple "update any document" or "create any document" grants, this is usually fine.
*
* For more complex grants, eg "update `posts` where `status` is `pending`", you will need
* to provide a sample document to check against.
*/
const dummyDocument = {_type: 'dummy', _id: 'dummy'}
/**
* Check if the current user has the grants necessary to perform the provided operation
* in the given dataset (must be within the same project, currently), using the provided
* document stub. If the type of properties of a document is not relevant for the grant
* check, you can omit the document stub property.
*
* Caveats (which will be (partially) fixed in an official hook):
* - Does not listen for changes in grants from server
* - Refetches/computes grants on each new mount (could be cached in hook if needed)
*
* @param options - The options to use for the check
* @returns `null` if loading/determining, `true` if the user has the grant, `false` otherwise
* @beta Workaround, as no public API for determining grants in different datasets exists yet
*/
export function useHasDocumentPermissionInDataset(options: {
dataset: string
permission: DocumentValuePermission
documentStub?: {_id: string; _type: string}
}): boolean | null {
const {dataset, permission, documentStub = dummyDocument} = options
// Note: this only works if the dataset is in the same project ID
const baseClient = useClient({apiVersion: '2023-01-01'})
// Don't create a new client on each invocation
const client = useMemo(() => baseClient.withConfig({dataset}), [baseClient, dataset])
const currentUser = useCurrentUser()
// `createGrantsStore` is marked `@internal` - it _may_ change in the future,
// but we'll provide a migration path if it does.
const grantStore = useMemo(() => createGrantsStore({client, currentUser}), [client, currentUser])
const [canUpdate, setCanUpdate] = useState<boolean | null>(null)
useEffect(() => {
const sub = grantStore
.checkDocumentPermission(permission, documentStub)
.subscribe(({granted}) => setCanUpdate(granted))
return () => sub.unsubscribe()
}, [grantStore, permission, documentStub])
return canUpdate
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment