mirror of
https://github.com/langgenius/dify.git
synced 2026-08-28 22:36:52 +08:00
126 lines
4.0 KiB
TypeScript
126 lines
4.0 KiB
TypeScript
'use client'
|
|
|
|
import type { AccessPolicyWithBindings, RemoveBindingPayload } from '@/models/access-control'
|
|
import { cn } from '@langgenius/dify-ui/cn'
|
|
import { toast } from '@langgenius/dify-ui/toast'
|
|
import { useCallback, useState } from 'react'
|
|
import AccessRuleRow from '@/app/components/header/account-setting/access-rules-page/access-rule-row'
|
|
import AddRuleTargetsModal from '@/app/components/header/account-setting/access-rules-page/add-rule-targets-modal'
|
|
import { useParams } from '@/next/navigation'
|
|
import { useUpdateAppAccessRuleBindings } from '@/service/access-control/use-app-access-config'
|
|
import { useUpdateDatasetAccessRuleBindings } from '@/service/access-control/use-dataset-access-config'
|
|
|
|
export type AccessRulesEditorProps = {
|
|
rules: AccessPolicyWithBindings[]
|
|
className?: string
|
|
}
|
|
|
|
const AccessRulesEditor = ({
|
|
rules,
|
|
className,
|
|
}: AccessRulesEditorProps) => {
|
|
const { appId } = useParams() as { appId: string }
|
|
const [currentRule, setCurrentRule] = useState<AccessPolicyWithBindings | null>(null)
|
|
|
|
const handleAddRole = useCallback((rule: AccessPolicyWithBindings) => {
|
|
setCurrentRule(rule)
|
|
}, [])
|
|
|
|
const handleCloseAddModal = useCallback(() => {
|
|
setCurrentRule(null)
|
|
}, [])
|
|
|
|
const { mutateAsync: updateAppAccessRuleBindings } = useUpdateAppAccessRuleBindings()
|
|
const { mutateAsync: updateDatasetAccessRuleBindings } = useUpdateDatasetAccessRuleBindings()
|
|
|
|
const handleAddSubmit = useCallback(
|
|
(selection: { roleIds: string[], memberIds: string[] }) => {
|
|
const { policy } = currentRule || {}
|
|
const { id: policyId, resource_type } = policy || {}
|
|
if (resource_type === 'app') {
|
|
updateAppAccessRuleBindings({
|
|
appId,
|
|
policyId: policyId || '',
|
|
role_ids: selection.roleIds,
|
|
account_ids: selection.memberIds,
|
|
}, {
|
|
onSuccess: () => {
|
|
toast.success('Rule binding updated successfully')
|
|
},
|
|
})
|
|
}
|
|
else if (resource_type === 'dataset') {
|
|
updateDatasetAccessRuleBindings({
|
|
datasetId: appId,
|
|
policyId: policyId || '',
|
|
role_ids: selection.roleIds,
|
|
account_ids: selection.memberIds,
|
|
}, {
|
|
onSuccess: () => {
|
|
toast.success('Rule binding updated successfully')
|
|
},
|
|
})
|
|
}
|
|
},
|
|
[appId, currentRule, updateAppAccessRuleBindings, updateDatasetAccessRuleBindings],
|
|
)
|
|
|
|
const handleRemoveRole = useCallback(
|
|
(payload: RemoveBindingPayload) => {
|
|
const { policy_id, role_ids, account_ids, resource_type } = payload
|
|
if (resource_type === 'app') {
|
|
updateAppAccessRuleBindings({
|
|
appId,
|
|
policyId: policy_id,
|
|
role_ids,
|
|
account_ids,
|
|
}, {
|
|
onSuccess: () => {
|
|
toast.success('Rule binding removed successfully')
|
|
},
|
|
})
|
|
}
|
|
else if (resource_type === 'dataset') {
|
|
updateDatasetAccessRuleBindings({
|
|
datasetId: appId,
|
|
policyId: policy_id,
|
|
role_ids,
|
|
account_ids,
|
|
}, {
|
|
onSuccess: () => {
|
|
toast.success('Rule binding removed successfully')
|
|
},
|
|
})
|
|
}
|
|
},
|
|
[appId, updateAppAccessRuleBindings, updateDatasetAccessRuleBindings],
|
|
)
|
|
|
|
return (
|
|
<div className={cn('flex flex-col', className)}>
|
|
{rules.map((rule, index) => (
|
|
<AccessRuleRow
|
|
key={rule.policy.id}
|
|
rule={rule}
|
|
showMenu={false}
|
|
onAddRole={handleAddRole}
|
|
onRemove={handleRemoveRole}
|
|
className={cn(index > 0 && 'border-t border-divider-subtle')}
|
|
/>
|
|
))}
|
|
|
|
{currentRule && (
|
|
<AddRuleTargetsModal
|
|
ruleName={currentRule.policy.name}
|
|
initialRoleIds={currentRule.roles.map(role => role.role_id)}
|
|
initialMemberIds={currentRule.accounts.map(account => account.account_id)}
|
|
onClose={handleCloseAddModal}
|
|
onSubmit={handleAddSubmit}
|
|
/>
|
|
)}
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export default AccessRulesEditor
|