mirror of
https://github.com/tiennm99/DocsGPT.git
synced 2026-10-12 20:15:26 +00:00
Lock fixed values in the tool editor for anyone but the owner
The server now refuses a fixed value or its filled-by-AI switch from team editors, so the editor shows them locked instead of failing the save.
This commit is contained in:
1 parent
b2d26c72ed
commit
793b8cb520
2 files changed
+40
-5
No files matched your search
@@ -567,6 +567,30 @@ describe('ToolConfig', () => {
|
||||
expect(credential && disabled(credential)).toBe(true);
|
||||
});
|
||||
|
||||
it('locks fixed values for anyone but the owner', async () => {
|
||||
// Even an editor who may change credentials: the server refuses a fixed
|
||||
// value from anyone but the owner.
|
||||
await render({
|
||||
...userTool,
|
||||
access: 'editor',
|
||||
allowed_actions: ['edit', 'edit_credentials', 'use', 'use_in_own'],
|
||||
} as UserToolType);
|
||||
await act(async () => {
|
||||
(
|
||||
container.querySelector('[class*="cursor-pointer"]') as HTMLElement
|
||||
).click();
|
||||
});
|
||||
const filled = container.querySelector(
|
||||
'[aria-label="settings.tools.filledByLLM"]',
|
||||
);
|
||||
expect(filled?.hasAttribute('disabled')).toBe(true);
|
||||
const tableInputs = Array.from(
|
||||
container.querySelectorAll<HTMLInputElement>('table input[data-slot]'),
|
||||
);
|
||||
// The description stays editable; the value is the fixed one.
|
||||
expect(tableInputs.at(-1)?.disabled).toBe(true);
|
||||
});
|
||||
|
||||
it('says why the credentials are locked for an editor without edit_credentials', async () => {
|
||||
await render({ ...configTool, ...editorNoCreds } as UserToolType);
|
||||
const note = container.querySelector('[data-slot="alert"]');
|
||||
|
||||
@@ -58,11 +58,14 @@ const BODY_TYPE_HINT_KEYS: Record<string, string> = {
|
||||
/**
|
||||
* What the caller may change on the open tool (`utils/accessUtils` `can`):
|
||||
* `canEdit` covers the name and the actions, `canEditCredentials` the
|
||||
* secrets, URLs and header / query values.
|
||||
* secrets, URLs and header / query values, and `canFixValues` whether a
|
||||
* parameter is filled by the AI or fixed, and its fixed value (the owner's
|
||||
* alone: the server refuses anyone else).
|
||||
*/
|
||||
const ToolAccessContext = React.createContext({
|
||||
canEdit: true,
|
||||
canEditCredentials: true,
|
||||
canFixValues: true,
|
||||
});
|
||||
|
||||
/** Maps a body content type to its hint's locale key suffix (JSON by default). */
|
||||
@@ -133,9 +136,10 @@ export default function ToolConfig({
|
||||
can(tool, 'edit_credentials') && !sharedOAuth && !ownerOnlyConnection;
|
||||
// Neither: the tool opens as a read-only view with no Save.
|
||||
const readOnly = !canEdit && !canEditCredentials;
|
||||
const canFixValues = isOwner(tool);
|
||||
const access = React.useMemo(
|
||||
() => ({ canEdit, canEditCredentials }),
|
||||
[canEdit, canEditCredentials],
|
||||
() => ({ canEdit, canEditCredentials, canFixValues }),
|
||||
[canEdit, canEditCredentials, canFixValues],
|
||||
);
|
||||
|
||||
const toggleUserActionExpand = (index: number) => {
|
||||
@@ -681,6 +685,7 @@ export default function ToolConfig({
|
||||
<Checkbox
|
||||
size="sm"
|
||||
checked={param[1].filled_by_llm}
|
||||
disabled={!canFixValues}
|
||||
id={uniqueKey}
|
||||
aria-label={t(
|
||||
'settings.tools.filledByLLM',
|
||||
@@ -738,7 +743,10 @@ export default function ToolConfig({
|
||||
<Input
|
||||
value={param[1].value}
|
||||
key={uniqueKey}
|
||||
disabled={param[1].filled_by_llm}
|
||||
disabled={
|
||||
param[1].filled_by_llm ||
|
||||
!canFixValues
|
||||
}
|
||||
size="sm"
|
||||
onChange={(e) => {
|
||||
setTool({
|
||||
@@ -1293,7 +1301,8 @@ function APIActionTable({
|
||||
) => void;
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
const { canEditCredentials } = React.useContext(ToolAccessContext);
|
||||
const { canEditCredentials, canFixValues } =
|
||||
React.useContext(ToolAccessContext);
|
||||
const idPrefix = React.useId();
|
||||
|
||||
const [action, setAction] = React.useState<APIActionType>(apiAction);
|
||||
@@ -1557,6 +1566,7 @@ function APIActionTable({
|
||||
id={`${idPrefix}-${section}-${index}-filled-by-llm`}
|
||||
aria-label={t('settings.tools.filledByLLM')}
|
||||
checked={param.filled_by_llm}
|
||||
disabled={!canFixValues}
|
||||
onCheckedChange={(checked) =>
|
||||
handlePropertyChange(
|
||||
section,
|
||||
@@ -1588,6 +1598,7 @@ function APIActionTable({
|
||||
value={param.value}
|
||||
disabled={
|
||||
param.filled_by_llm ||
|
||||
!canFixValues ||
|
||||
(section === 'query_params' && !canEditCredentials)
|
||||
}
|
||||
onChange={(e) =>
|
||||
|
||||
Reference in new issue
Block a user