Created
April 24, 2023 22:04
-
-
Save runeb/90b25608d91c5e1c1c18eb0c2a68e3ce to your computer and use it in GitHub Desktop.
Example useHasDocumentPermissionInDataset hook for evaluating grants and permissions in configurable dataset
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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> | |
) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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