-
Notifications
You must be signed in to change notification settings - Fork 451
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor(core): update managing permissions 2 (#8700)
- Loading branch information
Showing
19 changed files
with
218 additions
and
127 deletions.
There are no files selected for viewing
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
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
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
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
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
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
9 changes: 6 additions & 3 deletions
9
...e/__tests__/useReleasePermissions.test.ts → ...s__/createReleasePermissionsStore.test.ts
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
61 changes: 61 additions & 0 deletions
61
packages/sanity/src/core/releases/store/createReleasePermissionsStore.ts
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
import {isErrorWithDetails} from '../../error/types/isErrorWithDetails' | ||
import {type useReleasePermissionsValue} from './useReleasePermissions' | ||
|
||
type ReleasePermissionError = {details: {type: 'insufficientPermissionsError'}} | ||
|
||
/** | ||
* Checks if the error is a permission error | ||
* | ||
* @param error - the error to check | ||
* @returns true if the error is a permission error | ||
*/ | ||
export const isReleasePermissionError = (error: unknown): error is ReleasePermissionError => | ||
isErrorWithDetails(error) && error.details?.type === 'insufficientPermissionsError' | ||
|
||
/** | ||
* Store that contains if the user has permissions to perform a release action | ||
* And a guardrail to dry run requests to check if the user has permissions | ||
* | ||
* @returns an object with the following properties: | ||
* * checkWithPermissionGuard - a function that checks if the user has permissions to perform a release action by adding dryRun properties | ||
* * permissions - an object with the permissions for each action | ||
* | ||
* @internal | ||
*/ | ||
export function createReleasePermissionsStore(): useReleasePermissionsValue { | ||
let permissions: {[key: string]: boolean} = {} | ||
|
||
/** | ||
* Checks if a release action can be performed by running a dry run of the given action | ||
* | ||
* @param action - any of the actions from the {@link ReleaseOperationStore}, e.g. publishRelease should send in also the needed props | ||
* @param args - the arguments to pass to the action (release id, etc) | ||
* @returns true or false depending if the user can perform the action | ||
*/ | ||
const checkWithPermissionGuard = async <T extends (...args: any[]) => Promise<void> | void>( | ||
action: T, | ||
...args: Parameters<T> | ||
): Promise<boolean> => { | ||
if (permissions[action.name] === undefined) { | ||
try { | ||
await action(...args, { | ||
dryRun: true, | ||
skipCrossDatasetReferenceValidation: true, | ||
}) | ||
permissions = {...permissions, [action.name]: true} | ||
|
||
return true | ||
} catch (e) { | ||
permissions = {...permissions, [action.name]: false} | ||
|
||
return !isReleasePermissionError(e) | ||
} | ||
} else { | ||
return permissions[action.name] | ||
} | ||
} | ||
return { | ||
checkWithPermissionGuard: checkWithPermissionGuard, | ||
permissions, | ||
} | ||
} |
54 changes: 24 additions & 30 deletions
54
packages/sanity/src/core/releases/store/useReleasePermissions.ts
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,43 +1,37 @@ | ||
import {isErrorWithDetails} from '../../error/types/isErrorWithDetails' | ||
import {useMemo} from 'react' | ||
|
||
import {useResourceCache} from '../../store/_legacy/ResourceCacheProvider' | ||
import {createReleasePermissionsStore} from './createReleasePermissionsStore' | ||
|
||
const RELEASE_PERMISSIONS_RESOURCE_CACHE_NAMESPACE = 'ReleasePermissions' | ||
|
||
export interface useReleasePermissionsValue { | ||
checkWithPermissionGuard: <T extends (...args: any[]) => Promise<void> | void>( | ||
action: T, | ||
...args: Parameters<T> | ||
) => Promise<boolean> | ||
permissions: {[key: string]: boolean} | ||
} | ||
|
||
type ReleasePermissionError = {details: {type: 'insufficientPermissionsError'}} | ||
|
||
export const isReleasePermissionError = (error: unknown): error is ReleasePermissionError => | ||
isErrorWithDetails(error) && error.details?.type === 'insufficientPermissionsError' | ||
|
||
/** | ||
* @internal | ||
*/ | ||
export function useReleasePermissions(): useReleasePermissionsValue { | ||
/** | ||
* Checks if a release action can be performed by running a dry run of the given action | ||
* | ||
* @param action - any of the actions from the ReleaseOperationStore, e.g. publishRelease should send in also the needed props | ||
* @param args - the arguments to pass to the action (release id, etc) | ||
* @returns true or false depending if the user can perform the action | ||
*/ | ||
const checkWithPermissionGuard = async <T extends (...args: any[]) => Promise<void> | void>( | ||
action: T, | ||
...args: Parameters<T> | ||
): Promise<boolean> => { | ||
try { | ||
await action(...args, { | ||
dryRun: true, | ||
skipCrossDatasetReferenceValidation: true, | ||
}) | ||
return true | ||
} catch (e) { | ||
return !isReleasePermissionError(e) | ||
} | ||
} | ||
return { | ||
checkWithPermissionGuard: checkWithPermissionGuard, | ||
} | ||
const resourceCache = useResourceCache() | ||
|
||
return useMemo(() => { | ||
const releasePermissionsStore = | ||
resourceCache.get<useReleasePermissionsValue>({ | ||
dependencies: [null], | ||
namespace: RELEASE_PERMISSIONS_RESOURCE_CACHE_NAMESPACE, | ||
}) || createReleasePermissionsStore() | ||
|
||
resourceCache.set({ | ||
namespace: RELEASE_PERMISSIONS_RESOURCE_CACHE_NAMESPACE, | ||
value: releasePermissionsStore, | ||
dependencies: [null], | ||
}) | ||
|
||
return releasePermissionsStore | ||
}, [resourceCache]) | ||
} |
Oops, something went wrong.