mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-08-12 05:40:58 +00:00
feat(tenancy): implement workspace isolation
This commit is contained in:
@@ -24,6 +24,7 @@ import {
|
||||
} from './types';
|
||||
import { CustomApiError } from '@/app/infra/entities/common';
|
||||
import { PanelBody } from '../settings-dialog/panel-layout';
|
||||
import { useCurrentWorkspace } from '@/app/infra/http';
|
||||
|
||||
interface ModelsPanelProps {
|
||||
// True when this panel is the active section and the dialog is open.
|
||||
@@ -83,6 +84,9 @@ export default function ModelsPanel({
|
||||
onBlockingChange,
|
||||
}: ModelsPanelProps) {
|
||||
const { t } = useTranslation();
|
||||
const currentWorkspace = useCurrentWorkspace();
|
||||
const canManage =
|
||||
currentWorkspace?.permissions.includes('provider_secret.manage') ?? false;
|
||||
|
||||
const [providers, setProviders] = useState<ModelProvider[]>([]);
|
||||
const [accountType, setAccountType] = useState<'local' | 'space'>('local');
|
||||
@@ -270,17 +274,9 @@ export default function ModelsPanel({
|
||||
|
||||
async function handleSpaceLogin() {
|
||||
try {
|
||||
const token = localStorage.getItem('token');
|
||||
if (!token) {
|
||||
toast.error(t('common.error'));
|
||||
return;
|
||||
}
|
||||
const currentOrigin = window.location.origin;
|
||||
const redirectUri = `${currentOrigin}/auth/space/callback?mode=bind`;
|
||||
const response = await httpClient.getSpaceAuthorizeUrl(
|
||||
redirectUri,
|
||||
token,
|
||||
);
|
||||
const response = await httpClient.getSpaceBindAuthorizeUrl(redirectUri);
|
||||
window.location.href = response.authorize_url;
|
||||
} catch {
|
||||
toast.error(t('common.spaceLoginFailed'));
|
||||
@@ -544,6 +540,7 @@ export default function ModelsPanel({
|
||||
<ProviderCard
|
||||
key={provider.uuid}
|
||||
provider={provider}
|
||||
canManage={canManage}
|
||||
isLangBotModels={isLangBotModels}
|
||||
supportTypes={requesterSupportTypes[provider.requester]}
|
||||
isExpanded={expandedProviders.has(provider.uuid)}
|
||||
@@ -628,10 +625,12 @@ export default function ModelsPanel({
|
||||
)
|
||||
: t('models.providerCount', { count: otherProviders.length })}
|
||||
</span>
|
||||
<Button size="sm" variant="outline" onClick={handleCreateProvider}>
|
||||
<Plus className="h-4 w-4 mr-1" />
|
||||
{t('models.addProvider')}
|
||||
</Button>
|
||||
{canManage && (
|
||||
<Button size="sm" variant="outline" onClick={handleCreateProvider}>
|
||||
<Plus className="h-4 w-4 mr-1" />
|
||||
{t('models.addProvider')}
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Provider List */}
|
||||
|
||||
@@ -18,6 +18,7 @@ import { userInfo } from '@/app/infra/http';
|
||||
|
||||
interface ModelItemProps {
|
||||
model: LLMModel | EmbeddingModel;
|
||||
canManage: boolean;
|
||||
modelType: ModelType;
|
||||
isLangBotModels: boolean;
|
||||
editModelPopoverOpen: string | null;
|
||||
@@ -71,6 +72,7 @@ function convertExtraArgsToArray(extraArgs?: object): ExtraArg[] {
|
||||
|
||||
export default function ModelItem({
|
||||
model,
|
||||
canManage,
|
||||
modelType,
|
||||
isLangBotModels,
|
||||
editModelPopoverOpen,
|
||||
@@ -149,7 +151,7 @@ export default function ModelItem({
|
||||
|
||||
// Check if popover should be disabled (space models when not logged in)
|
||||
const isPopoverDisabled =
|
||||
isLangBotModels && userInfo?.account_type !== 'space';
|
||||
!canManage || (isLangBotModels && userInfo?.account_type !== 'space');
|
||||
|
||||
return (
|
||||
<Popover
|
||||
@@ -193,7 +195,7 @@ export default function ModelItem({
|
||||
</Badge>
|
||||
)}
|
||||
</div>
|
||||
{!isLangBotModels && (
|
||||
{canManage && !isLangBotModels && (
|
||||
<Popover
|
||||
open={isDeleteOpen}
|
||||
onOpenChange={(open) =>
|
||||
|
||||
@@ -38,6 +38,7 @@ import AddModelPopover from './AddModelPopover';
|
||||
|
||||
interface ProviderCardProps {
|
||||
provider: ModelProvider;
|
||||
canManage: boolean;
|
||||
isLangBotModels?: boolean;
|
||||
supportTypes?: string[];
|
||||
isExpanded: boolean;
|
||||
@@ -101,6 +102,7 @@ function maskApiKey(key: string): string {
|
||||
|
||||
export default function ProviderCard({
|
||||
provider,
|
||||
canManage,
|
||||
isLangBotModels = false,
|
||||
supportTypes,
|
||||
isExpanded,
|
||||
@@ -196,7 +198,7 @@ export default function ProviderCard({
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center gap-1 ml-2 shrink-0">
|
||||
{isLangBotModels && accountType !== 'space' && (
|
||||
{canManage && isLangBotModels && accountType !== 'space' && (
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
@@ -232,7 +234,7 @@ export default function ProviderCard({
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
{!isLangBotModels && (
|
||||
{canManage && !isLangBotModels && (
|
||||
<>
|
||||
<Button
|
||||
variant="ghost"
|
||||
@@ -317,7 +319,7 @@ export default function ProviderCard({
|
||||
) : (
|
||||
<div />
|
||||
)}
|
||||
{!isLangBotModels && (
|
||||
{canManage && !isLangBotModels && (
|
||||
<div className="flex items-center gap-1">
|
||||
<AddModelPopover
|
||||
isOpen={
|
||||
@@ -404,6 +406,7 @@ export default function ProviderCard({
|
||||
<ModelItem
|
||||
key={model.uuid}
|
||||
model={model}
|
||||
canManage={canManage}
|
||||
modelType="llm"
|
||||
isLangBotModels={isLangBotModels}
|
||||
editModelPopoverOpen={editModelPopoverOpen}
|
||||
@@ -441,6 +444,7 @@ export default function ProviderCard({
|
||||
<ModelItem
|
||||
key={model.uuid}
|
||||
model={model}
|
||||
canManage={canManage}
|
||||
modelType="embedding"
|
||||
isLangBotModels={isLangBotModels}
|
||||
editModelPopoverOpen={editModelPopoverOpen}
|
||||
@@ -472,6 +476,7 @@ export default function ProviderCard({
|
||||
<ModelItem
|
||||
key={model.uuid}
|
||||
model={model}
|
||||
canManage={canManage}
|
||||
modelType="rerank"
|
||||
isLangBotModels={isLangBotModels}
|
||||
editModelPopoverOpen={editModelPopoverOpen}
|
||||
|
||||
Reference in New Issue
Block a user