Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 19 additions & 68 deletions webapp/src/components/ChatAppForm2.tsx
Original file line number Diff line number Diff line change
@@ -1,61 +1,26 @@
import * as API from '@api';

import { AgentCreatedDisplay } from 'components/apps/AgentCreatedDisplay';
import { AgentSelectDisplay } from 'components/apps/AgentSelectDisplay';
import { CreateAgentSheet } from 'components/apps/CreateAgentSheet';
import { InsightChat } from 'components/apps/InsightChat';
import Spinner from 'components/Spinner';
import { useAccountContext } from 'context/account';
import { useStepContext } from 'context/stepwrapper';
import { useThemeContext } from 'context/themecontext';
import { AgentsDataReturnType } from 'controllers/agent';
import { AppsDataReturnType } from 'controllers/app';
import { Model } from 'db/model';
import useAutocompleteDropdown from 'hooks/useAutoCompleteDropdown';
import { ChevronDown, Circle, Layout, Pencil, SendHorizonal, Trash2 } from 'lucide-react';
import { MultiSelect } from 'modules/components/multi-select';
import { Circle, Pencil, SendHorizonal, Trash2 } from 'lucide-react';
import { Button } from 'modules/components/ui/button';
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger
} from 'modules/components/ui/dropdown-menu';
import { useRouter } from 'next/router';
// import agents from 'pages/[resourceSlug]/agents';

import { usePostHog } from 'posthog-js/react';
import { useEffect, useState } from 'react';
import { toast } from 'react-toastify';
import { useAgentStore } from 'store/agent';
import { Agent } from 'struct/agent';
import { App, AppType } from 'struct/app';
import { ChatAppAllowedModels } from 'struct/model';
import { SharingMode } from 'struct/sharing';
import { ToolType } from 'struct/tool';

import AddEmailModal from './AddEmailModal';
import ConfirmModal from './ConfirmModal';
import CreateDatasourceModal from './CreateDatasourceModal';
import CreateModelModal from './CreateModelModal';
import CreateToolModal from './modal/CreateToolModal';
import SharingModeSelect from './SharingModeSelect';
import CreateVariableModal from './variables/CreateVariableModal';

const chatAppTaglines = [
'Build single agent chat bots (like GPTS)',
'Integrate RAG datasources',
'Add custom agent',
'Integrate custom tools',
'Embed your chat app via IFrame'
];

const processAppTaglines = [
'Build Multi-Agent Process Apps (powered by Crew AI)',
'Integrate RAG datasources',
'Add custom code tools',
'Add tasks',
'Embed your process app via IFrame'
];
import { SharingMode } from 'struct/sharing';
import { useAccountContext } from 'context/account';
import Link from 'next/link';

export default function Apps({
app,
Expand Down Expand Up @@ -126,6 +91,8 @@
const router = useRouter();
const { resourceSlug } = router.query;

// const { step, setStep } = useStepContext();

const [sharingMode, setSharingMode] = useState(app?.sharingConfig?.mode || SharingMode.TEAM);
const [shareLinkShareId, setShareLinkShareId] = useState(editing ? app?.shareLinkShareId : null);
const [appName, setAppName] = useState(app?.name || 'Untitled Chat App');
Expand Down Expand Up @@ -342,7 +309,9 @@
return (
<main className='text-foreground flex flex-col gap-2'>
<div className='flex gap-2 mb-2 text-sm'>
<h4 className='text-gray-700 font-semibold'>Apps</h4>
<Link href={`/${resourceSlug}/apps`}>

Check warning

Code scanning / CodeQL

Client-side URL redirect Medium

Untrusted URL redirection depends on a
user-provided value
.

Copilot Autofix

AI over 1 year ago

To fix the problem, we should avoid using user input directly in the URL redirection. Instead, we can maintain a list of authorized redirects and choose from that list based on the user input. This ensures that only safe and predefined URLs are used for redirection.

  1. Create a list of authorized redirects.
  2. Validate the resourceSlug against this list before constructing the URL.
  3. If the resourceSlug is not in the list, handle the error appropriately (e.g., redirect to a default safe page or show an error message).
Suggested changeset 1
webapp/src/components/ChatAppForm2.tsx

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/webapp/src/components/ChatAppForm2.tsx b/webapp/src/components/ChatAppForm2.tsx
--- a/webapp/src/components/ChatAppForm2.tsx
+++ b/webapp/src/components/ChatAppForm2.tsx
@@ -92,2 +92,4 @@
 	const { resourceSlug } = router.query;
+	const authorizedSlugs = ['validSlug1', 'validSlug2', 'validSlug3']; // Add your authorized slugs here
+	const isValidSlug = authorizedSlugs.includes(resourceSlug);
 
@@ -311,5 +313,11 @@
 			<div className='flex gap-2 mb-2 text-sm'>
-				<Link href={`/${resourceSlug}/apps`}>
-					<h4 className='text-gray-700 font-semibold cursor-pointer'>Apps</h4>
-				</Link>
+				{isValidSlug ? (
+					<Link href={`/${resourceSlug}/apps`}>
+						<h4 className='text-gray-700 font-semibold cursor-pointer'>Apps</h4>
+					</Link>
+				) : (
+					<Link href="/default/apps"> {/* Redirect to a default safe page */}
+						<h4 className='text-gray-700 font-semibold cursor-pointer'>Apps</h4>
+					</Link>
+				)}
 				<span className='text-gray-500'>&gt;</span>
EOF
@@ -92,2 +92,4 @@
const { resourceSlug } = router.query;
const authorizedSlugs = ['validSlug1', 'validSlug2', 'validSlug3']; // Add your authorized slugs here
const isValidSlug = authorizedSlugs.includes(resourceSlug);

@@ -311,5 +313,11 @@
<div className='flex gap-2 mb-2 text-sm'>
<Link href={`/${resourceSlug}/apps`}>
<h4 className='text-gray-700 font-semibold cursor-pointer'>Apps</h4>
</Link>
{isValidSlug ? (
<Link href={`/${resourceSlug}/apps`}>
<h4 className='text-gray-700 font-semibold cursor-pointer'>Apps</h4>
</Link>
) : (
<Link href="/default/apps"> {/* Redirect to a default safe page */}
<h4 className='text-gray-700 font-semibold cursor-pointer'>Apps</h4>
</Link>
)}
<span className='text-gray-500'>&gt;</span>
Copilot is powered by AI and may make mistakes. Always verify output.
<h4 className='text-gray-700 font-semibold cursor-pointer'>Apps</h4>
</Link>
<span className='text-gray-500'>&gt;</span>
<h4 className='text-gray-700 font-semibold'>Create App</h4>
<span className='text-gray-500'>&gt;</span>
Expand All @@ -355,8 +324,7 @@
<div className='flex border border-gray-200 rounded-lg'>
<form
className='flex flex-col justify-between border border-gray-200 rounded-l-lg w-full minh-[790px]'
onSubmit={appPost}
>
onSubmit={appPost}>
<article className='flex flex-col p-5 gap-6'>
<div className='flex items-center gap-3 h-24'>
<img className='rounded-3xl' src='/apps/identicon.png' />
Expand Down Expand Up @@ -388,8 +356,7 @@
setAppName('');
}
}}
className='hover:text-[#4F46E5] transition-colors'
>
className='hover:text-[#4F46E5] transition-colors'>
<Pencil width={20} />
</button>
</div>
Expand Down Expand Up @@ -465,8 +432,7 @@
<div key={starter.id} className='flex items-center gap-2'>
<div
className='bg-gray-50 px-4 py-3 w-full border border-gray-300 rounded-lg'
onClick={() => setEditingStarterId(starter.id)}
>
onClick={() => setEditingStarterId(starter.id)}>
{editingStarterId === starter.id ? (
<input
type='text'
Expand Down Expand Up @@ -503,22 +469,10 @@
))}
<p
className='text-[#4F46E5] cursor-pointer self-end hover:text-[#3730a3]'
onClick={handleAddStarter}
>
onClick={handleAddStarter}>
+ Add
</p>
</div>
{/* <div className='w-full flex items-center justify-between bg-gray-100 p-6 rounded-lg'>
<p className='text-gray-500'>Display Settings</p>
<DropdownMenu>
<DropdownMenuTrigger className='bg-background rounded-sm border border-gray-200'>
<ChevronDown width={25} color='#6B7280' />
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuItem>Dropdown Item</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</div> */}

<SharingModeSelect
sharingMode={sharingMode}
Expand All @@ -538,8 +492,7 @@
<div className='sm:col-span-'>
<label
htmlFor='maxMessages'
className='block text-sm font-medium leading-6 text-gray-900 dark:text-slate-400'
>
className='block text-sm font-medium leading-6 text-gray-900 dark:text-slate-400'>
Max Messages
</label>
<input
Expand All @@ -559,15 +512,14 @@
<Button
type='button'
variant='ghost'
className='bg-transparent text-foreground hover:bg-transparent hover:text-foreground p-0 border-0 shadow-none outline-none'
>
onClick={() => (editing ? callback?.() : router.back())}
className='bg-transparent text-foreground hover:bg-transparent hover:text-foreground p-0 border-0 shadow-none outline-none'>
Cancel
</Button>
<Button
onClick={() => setRun(false)}
variant='ghost'
className='ml-auto bg-gradient-to-r from-[#4F46E5] to-[#612D89] text-white font-medium text-sm py-2 hover:text-white'
>
className='ml-auto bg-gradient-to-r from-[#4F46E5] to-[#612D89] text-white font-medium text-sm py-2 hover:text-white'>
Save
</Button>
<Button
Expand All @@ -576,8 +528,7 @@
setRun(true);
}}
variant='ghost'
className='ml-2 bg-gradient-to-r from-[#4F46E5] to-[#612D89] text-white font-medium text-sm py-2 hover:text-white'
>
className='ml-2 bg-gradient-to-r from-[#4F46E5] to-[#612D89] text-white font-medium text-sm py-2 hover:text-white'>
Save & Launch
</Button>
</article>
Expand Down
24 changes: 20 additions & 4 deletions webapp/src/pages/[resourceSlug]/app/[appId]/edit.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as API from '@api';
import { ChevronLeftIcon, PhotoIcon, UserCircleIcon } from '@heroicons/react/24/solid';
import ChatAppForm from 'components/ChatAppForm';
import ChatAppForm2 from 'components/ChatAppForm2';
import CrewAppForm from 'components/CrewAppForm';
import Spinner from 'components/Spinner';
import { useAccountContext } from 'context/account';
Expand All @@ -9,6 +9,7 @@ import Link from 'next/link';
import { useRouter } from 'next/router';
import React, { useEffect, useState } from 'react';
import { AppType } from 'struct/app';
import { Button } from 'modules/components/ui/button';

export default function EditApp(props) {
const [accountContext]: any = useAccountContext();
Expand All @@ -35,6 +36,10 @@ export default function EditApp(props) {
fetchAppFormData();
}, [resourceSlug]);

const handleBack = () => {
router.push(`/${resourceSlug}/apps`);
Comment thread Fixed
};

if (app == null) {
return <Spinner />;
}
Expand All @@ -45,12 +50,17 @@ export default function EditApp(props) {
<title>{`Edit App - ${teamName}`}</title>
</Head>

<div className='border-b pb-2 my-2 mb-6'>
<h3 className='font-semibold text-gray-900'>Edit App - {app.name}</h3>
<div className='border-b pb-2 my-2 mb-6 flex items-center justify-between'>
<div className='flex items-center gap-2'>
<Button variant='ghost' className='hover:bg-transparent p-0' onClick={handleBack}>
<ChevronLeftIcon className='h-6 w-6' />
</Button>
<h3 className='font-semibold text-gray-900'>Edit App - {app.name}</h3>
</div>
</div>

{(app.type as AppType) === AppType.CHAT ? (
<ChatAppForm
<ChatAppForm2
editing={true}
app={app}
fetchFormData={fetchAppFormData}
Expand All @@ -61,6 +71,9 @@ export default function EditApp(props) {
toolChoices={tools}
whiteListSharingChoices={teamMembers}
variableChoices={variables}
callback={() => {
router.push(`/${resourceSlug}/apps`);
Comment thread Fixed
}}
/>
) : (
<CrewAppForm
Expand All @@ -75,6 +88,9 @@ export default function EditApp(props) {
whiteListSharingChoices={teamMembers}
// toolChoices={tools}
variableChoices={variables}
callback={() => {
router.push(`/${resourceSlug}/apps`);
Comment thread Fixed
}}
/>
)}
</>
Expand Down
Loading
Loading