fix(权限): 修复版本详情写入权限校验
This commit is contained in:
@@ -31,7 +31,7 @@ import { formatDateTime, formatLocalDate } from '@/lib/format';
|
||||
import { getVersionLinkedRequirementCandidates } from '@/lib/requirement-selector';
|
||||
import { getRequirementVersionSelectionPatch, getRequirementVersionUnlinkPatch } from '@/lib/requirement-version-link';
|
||||
import { calcBugSeverityRanking, calcPersonalEffortRanking, calcStageEffortMetrics, calcVersionOverviewEffortTotals } from '@/lib/version-overview';
|
||||
import { addVersionMembers, DEFAULT_VERSION_MEMBER_ROLE, filterVersionMemberCandidates } from '@/lib/version-members';
|
||||
import { addVersionMembers, canWriteVersionWork, DEFAULT_VERSION_MEMBER_ROLE, filterVersionMemberCandidates } from '@/lib/version-members';
|
||||
import { addRecommendedVersionMembers, getDefaultRecommendedMemberNames, recommendVersionMembers, type MemberRecommendationGroup, type RecommendableRole } from '@/lib/member-recommendation';
|
||||
import { getRequirementCoverageSummary } from '@/lib/version-plan';
|
||||
import { buildVersionDataScope, selectVersionDataScope, type VersionDataScope } from '@/lib/version-data-scope';
|
||||
@@ -85,6 +85,12 @@ const TABS = [
|
||||
{ key: 'bugs', label: 'BUG', permission: 'version.bug:view' },
|
||||
];
|
||||
|
||||
const PLAN_MANAGE_PERMISSION = {
|
||||
research: 'version.research:manage',
|
||||
product: 'version.product_plan:manage',
|
||||
ui: 'version.ui_plan:manage',
|
||||
} as const;
|
||||
|
||||
export default function VersionDetailPage() {
|
||||
const params = useParams();
|
||||
const router = useRouter();
|
||||
@@ -302,6 +308,20 @@ export default function VersionDetailPage() {
|
||||
);
|
||||
}
|
||||
|
||||
const versionMembers = version.members ?? [];
|
||||
const canWriteVersionPermission = (permission: string) => canWriteVersionWork({
|
||||
role: currentRole,
|
||||
permission,
|
||||
currentUserName,
|
||||
versionMembers,
|
||||
readOnly: versionReadonly,
|
||||
});
|
||||
const canManageRequirements = canWriteVersionPermission('version.req:manage');
|
||||
const canManageDevTasks = canWriteVersionPermission('version.devtask:manage');
|
||||
const canManageTestCases = canWriteVersionPermission('version.testcase:manage');
|
||||
const canManageBugs = ['version.bug:create', 'version.bug:edit', 'version.bug:delete']
|
||||
.some((permission) => canWriteVersionPermission(permission));
|
||||
|
||||
const scopedVersionData = versionScope!;
|
||||
const appDataScopedVersionData = appDataVersionScope ?? scopedVersionData;
|
||||
const displayRequirements = requirementsLoaded ? requirements : scopedVersionData.requirements;
|
||||
@@ -987,9 +1007,9 @@ export default function VersionDetailPage() {
|
||||
devTasks={displayDevTasks}
|
||||
versionMembers={version.members ?? []}
|
||||
currentUserName={user?.name ?? ''}
|
||||
readOnly={versionReadonly || !requirementWriteReady}
|
||||
readOnly={versionReadonly || !requirementWriteReady || !canManageRequirements}
|
||||
onLink={(ids, addedBy) => {
|
||||
if (versionReadonly || !requirementWriteReady) return;
|
||||
if (versionReadonly || !requirementWriteReady || !canManageRequirements) return;
|
||||
ids.forEach((id) => {
|
||||
const requirement = displayRequirements.find((item) => item.id === id);
|
||||
if (!requirement) return;
|
||||
@@ -1000,7 +1020,7 @@ export default function VersionDetailPage() {
|
||||
});
|
||||
}}
|
||||
onUnlink={(id) => {
|
||||
if (versionReadonly || !requirementWriteReady) return;
|
||||
if (versionReadonly || !requirementWriteReady || !canManageRequirements) return;
|
||||
const requirement = displayRequirements.find((item) => item.id === id);
|
||||
if (!requirement) return;
|
||||
updateRequirement(id, {
|
||||
@@ -1009,7 +1029,7 @@ export default function VersionDetailPage() {
|
||||
});
|
||||
}}
|
||||
onCreateChange={(data) => {
|
||||
if (versionReadonly || !requirementWriteReady) return;
|
||||
if (versionReadonly || !requirementWriteReady || !canManageRequirements) return;
|
||||
createRequirement({
|
||||
...data,
|
||||
productId: version.productId,
|
||||
@@ -1043,9 +1063,9 @@ export default function VersionDetailPage() {
|
||||
versionMembers={version.members ?? []}
|
||||
linkedRequirements={versionLinkedReqs}
|
||||
allRequirements={displayRequirements}
|
||||
readOnly={versionReadonly || !planWriteReady}
|
||||
readOnly={versionReadonly || !planWriteReady || !canWriteVersionPermission(PLAN_MANAGE_PERMISSION[pt])}
|
||||
onCreate={(data) => {
|
||||
if (versionReadonly || !planWriteReady) return;
|
||||
if (versionReadonly || !planWriteReady || !canWriteVersionPermission(PLAN_MANAGE_PERMISSION[pt])) return;
|
||||
createPlan(data);
|
||||
if ((pt === 'product') && data.linkedRequirementIds?.length) {
|
||||
data.linkedRequirementIds.forEach((rid) => {
|
||||
@@ -1061,7 +1081,7 @@ export default function VersionDetailPage() {
|
||||
}
|
||||
}}
|
||||
onUpdate={(id, data) => {
|
||||
if (versionReadonly || !planWriteReady) return;
|
||||
if (versionReadonly || !planWriteReady || !canWriteVersionPermission(PLAN_MANAGE_PERMISSION[pt])) return;
|
||||
updatePlan(id, data);
|
||||
if ((pt === 'product') && data.linkedRequirementIds && data.owner) {
|
||||
data.linkedRequirementIds.forEach((rid) => {
|
||||
@@ -1071,11 +1091,11 @@ export default function VersionDetailPage() {
|
||||
}
|
||||
}}
|
||||
onComplete={(id, result) => {
|
||||
if (versionReadonly || !planWriteReady) return;
|
||||
if (versionReadonly || !planWriteReady || !canWriteVersionPermission(PLAN_MANAGE_PERMISSION[pt])) return;
|
||||
return completePlan(id, result);
|
||||
}}
|
||||
onDelete={(id) => {
|
||||
if (versionReadonly || !planWriteReady) return;
|
||||
if (versionReadonly || !planWriteReady || !canWriteVersionPermission(PLAN_MANAGE_PERMISSION[pt])) return;
|
||||
deletePlan(id);
|
||||
}}
|
||||
/>
|
||||
@@ -1086,7 +1106,7 @@ export default function VersionDetailPage() {
|
||||
versionId={version.id}
|
||||
requirementIds={displayRequirementIds}
|
||||
versionDeadline={version.expectedReleaseDate ?? undefined}
|
||||
readOnly={versionReadonly || !devTaskWriteReady}
|
||||
readOnly={versionReadonly || !devTaskWriteReady || !canManageDevTasks}
|
||||
versionTasks={displayDevTasks}
|
||||
versionRequirements={displayRequirements}
|
||||
/>
|
||||
@@ -1094,7 +1114,7 @@ export default function VersionDetailPage() {
|
||||
<TestCaseTab
|
||||
versionId={version.id}
|
||||
requirementIds={displayRequirementIds}
|
||||
readOnly={versionReadonly || !testCaseWriteReady}
|
||||
readOnly={versionReadonly || !testCaseWriteReady || !canManageTestCases}
|
||||
versionCases={displayTestCases}
|
||||
versionBugs={displayBugs}
|
||||
versionDevTasks={displayDevTasks}
|
||||
@@ -1104,7 +1124,7 @@ export default function VersionDetailPage() {
|
||||
<BugTab
|
||||
versionId={version.id}
|
||||
requirementIds={displayRequirementIds}
|
||||
readOnly={versionReadonly || !bugWriteReady}
|
||||
readOnly={versionReadonly || !bugWriteReady || !canManageBugs}
|
||||
versionBugs={displayBugs}
|
||||
versionTestCases={displayTestCases}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user