| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475 |
- import React, { useEffect, useState } from 'react';
- import type { UseFormRegisterReturn } from 'react-hook-form';
- import { parseScopes } from '~/client/util/scope-util';
- import { useIsAdmin } from '~/stores-universal/context';
- import type { Scope } from '../../../interfaces/scope';
- import { SCOPE } from '../../../interfaces/scope';
- import { AccessTokenScopeList } from './AccessTokenScopeList';
- /**
- * Props for AccessTokenScopeSelect
- */
- type AccessTokenScopeSelectProps = {
- /** React Hook Form's register function for a field named "scopes" */
- register: UseFormRegisterReturn<'scopes'>;
- watch: string[];
- };
- /**
- * Displays a list of permissions in a recursive, nested checkbox interface.
- */
- export const AccessTokenScopeSelect: React.FC<AccessTokenScopeSelectProps> = ({ register, watch }) => {
- const [disabledScopes, setDisabledScopes] = useState<Set<Scope>>(new Set());
- const { data: isAdmin } = useIsAdmin();
- const ScopesMap = parseScopes({ scopes: SCOPE, isAdmin });
- const extractScopes = (obj: Record<string, any>): string[] => {
- let result: string[] = [];
- Object.values(obj).forEach((value) => {
- if (typeof value === 'string') {
- result.push(value);
- }
- else if (typeof value === 'object' && !Array.isArray(value)) {
- result = result.concat(extractScopes(value));
- }
- });
- return result;
- };
- const Scopes: string[] = extractScopes(ScopesMap);
- useEffect(() => {
- const selectedScopes = watch || [];
- // Create a set of scopes to disable based on prefixes
- const disabledSet = new Set<Scope>();
- selectedScopes.forEach((scope) => {
- // Check if the scope is in the form `xxx:*`
- if (scope.endsWith(':*')) {
- // Convert something like `read:*` into the prefix `read:`
- const prefix = scope.replace(':*', ':');
- // Disable all scopes that start with the prefix (but are not the selected scope itself)
- Scopes.forEach((s:Scope) => {
- if (s.startsWith(prefix) && s !== scope) {
- disabledSet.add(s);
- }
- });
- }
- });
- setDisabledScopes(disabledSet);
- }, [watch, Scopes]);
- return (
- <div className="border rounded">
- <AccessTokenScopeList scopeObject={ScopesMap} register={register} disabledScopes={disabledScopes} />
- </div>
- );
- };
|