Răsfoiți Sursa

use Scope type

NaokiHigashi28 1 an în urmă
părinte
comite
80d561ec27

+ 4 - 6
apps/app/src/client/components/Me/AccessTokenScopeList.tsx

@@ -6,13 +6,13 @@ import type { Scope } from '../../../interfaces/scope';
 
 
 interface scopeObject {
-  [key: string]: string | scopeObject;
+  [key: string]: Scope | scopeObject;
 }
 
 interface AccessTokenScopeListProps {
   scopeObject: scopeObject;
   register: UseFormRegisterReturn<'scopes'>;
-  disabledScopes: Scope[]
+  disabledScopes: Set<Scope>
   level?: number;
 }
 
@@ -33,13 +33,12 @@ export const AccessTokenScopeList: React.FC<AccessTokenScopeListProps> = ({
   return (
     <>
       {entries.map(([scopeKey, scopeValue], idx) => {
-        const isNestedObject = typeof scopeValue === 'object' && !Array.isArray(scopeValue);
         // Indent according to the level
         const indentationStyle = { marginLeft: `${(level + 1) * 20}px` };
         // Example: Insert <hr> only for levels 0 or 1, except for the first item
         const showHr = (level === 0 || level === 1) && idx !== 0;
 
-        if (isNestedObject) {
+        if (typeof scopeValue === 'object') {
           return (
             <div key={scopeKey}>
               {showHr && <hr className="my-1" />}
@@ -60,7 +59,6 @@ export const AccessTokenScopeList: React.FC<AccessTokenScopeListProps> = ({
             </div>
           );
         }
-
         // If it's a string, render a checkbox
         return (
           <div key={scopeKey} className="row my-1">
@@ -70,7 +68,7 @@ export const AccessTokenScopeList: React.FC<AccessTokenScopeListProps> = ({
                 style={indentationStyle}
                 type="checkbox"
                 id={scopeValue as string}
-                disabled={disabledScopes.has(scopeValue as string)} // 無効化
+                disabled={disabledScopes.has(scopeValue)}
                 value={scopeValue as string}
                 {...register}
               />

+ 8 - 6
apps/app/src/client/components/Me/AccessTokenScopeSelect.tsx

@@ -3,6 +3,7 @@ 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';
@@ -15,15 +16,16 @@ import { AccessTokenScopeList } from './AccessTokenScopeList';
 type AccessTokenScopeSelectProps = {
   /** React Hook Form's register function for a field named "scopes" */
   register: UseFormRegisterReturn<'scopes'>;
-  watch: Scope[];
+  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<string>>(new Set());
-  const ScopesMap = parseScopes({ scopes: SCOPE, isAdmin: false });
+  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[] = [];
@@ -45,7 +47,7 @@ export const AccessTokenScopeSelect: React.FC<AccessTokenScopeSelectProps> = ({
     const selectedScopes = watch || [];
 
     // Create a set of scopes to disable based on prefixes
-    const disabledSet = new Set<string>();
+    const disabledSet = new Set<Scope>();
 
     selectedScopes.forEach((scope) => {
       // Check if the scope is in the form `xxx:*`
@@ -54,7 +56,7 @@ export const AccessTokenScopeSelect: React.FC<AccessTokenScopeSelectProps> = ({
         const prefix = scope.replace(':*', ':');
 
         // Disable all scopes that start with the prefix (but are not the selected scope itself)
-        Scopes.forEach((s) => {
+        Scopes.forEach((s:Scope) => {
           if (s.startsWith(prefix) && s !== scope) {
             disabledSet.add(s);
           }
@@ -63,7 +65,7 @@ export const AccessTokenScopeSelect: React.FC<AccessTokenScopeSelectProps> = ({
     });
 
     setDisabledScopes(disabledSet);
-  }, [watch]);
+  }, [watch, Scopes]);
 
   return (
     <div className="border rounded">

+ 4 - 3
apps/app/src/client/util/scope-util.ts

@@ -1,7 +1,8 @@
+import type { Scope } from '~/interfaces/scope';
 
 // Data structure for the final merged scopes
 interface ScopeMap {
-  [key: string]: string | ScopeMap;
+  [key: string]: Scope | ScopeMap;
 }
 
 // Input object with arbitrary action keys (e.g., READ, WRITE)
@@ -35,7 +36,7 @@ function parseSubScope(
       for (const action of actions) {
         const val = subObjForActions[action]?.[ck];
         if (typeof val === 'string') {
-          result[`${action.toLowerCase()}:${parentKey.toLowerCase()}:all`] = val;
+          result[`${action.toLowerCase()}:${parentKey.toLowerCase()}:all`] = val as Scope;
         }
       }
       continue;
@@ -75,7 +76,7 @@ export function parseScopes({ scopes, isAdmin = false }: { scopes: ScopesInput ;
       for (const action of actions) {
         const val = scopes[action]?.[key];
         if (typeof val === 'string') {
-          allObj[`${action.toLowerCase()}:all`] = val;
+          allObj[`${action.toLowerCase()}:all`] = val as Scope;
         }
       }
       result.ALL = allObj;