feat(P15A-1,P15A-5): 解耦请假审批权限
这个提交包含在:
@@ -95,7 +95,8 @@ async function leaveRoutes(fastify) {
|
||||
fastify.post(
|
||||
"/leave-requests",
|
||||
{
|
||||
preHandler: fastify.authenticate,
|
||||
schema: { tags: ["Leave"], summary: "Create Leave Request" },
|
||||
preHandler: fastify.requireEntityPermission("leave", "create"),
|
||||
},
|
||||
async (request, reply) => {
|
||||
const body = parseCreateBody(request.body);
|
||||
@@ -131,6 +132,7 @@ async function leaveRoutes(fastify) {
|
||||
fastify.get(
|
||||
"/leave-requests/:id",
|
||||
{
|
||||
schema: { tags: ["Leave"], summary: "Get Leave Request" },
|
||||
preHandler: fastify.authenticate,
|
||||
},
|
||||
async (request, reply) => {
|
||||
@@ -159,7 +161,7 @@ async function leaveRoutes(fastify) {
|
||||
});
|
||||
}
|
||||
|
||||
const canViewAll = fastify.hasPermission(request.employee, "expense.view_all");
|
||||
const canViewAll = fastify.hasPermission(request.employee, "leave.view_all");
|
||||
if (!canViewAll && leave.owner_id !== request.employee.id) {
|
||||
throw new AppError({
|
||||
code: "PERM_001",
|
||||
@@ -185,7 +187,8 @@ async function leaveRoutes(fastify) {
|
||||
fastify.post(
|
||||
"/leave-requests/:id/submit",
|
||||
{
|
||||
preHandler: fastify.authenticate,
|
||||
schema: { tags: ["Leave"], summary: "Submit Leave Request" },
|
||||
preHandler: fastify.requireEntityPermission("leave", "submit"),
|
||||
},
|
||||
async (request, reply) => {
|
||||
const leaveId = parseLeaveId(request.params?.id);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
const { z } = require("zod");
|
||||
const { AppError } = require("../utils/AppError");
|
||||
const { sendData } = require("../utils/reply");
|
||||
const { resolvePermissionsForRoles, hasPermission, ROLE_PERMISSIONS } = require("../constants/permissions");
|
||||
const { resolvePermissionsForRoles, hasPermission, ROLE_PERMISSIONS, resolveEntityPermission } = require("../constants/permissions");
|
||||
const { getWorkflowStepsSnapshot, resolveActionableStep, toMoneyString } = require("../utils/workflow");
|
||||
const {
|
||||
createNotifications,
|
||||
@@ -199,7 +199,8 @@ function listAllowedActionsForTask(request, task, actionable) {
|
||||
}
|
||||
|
||||
const actions = [];
|
||||
if (hasPermission(request.employee.permissionCodes, "expense.approve")) {
|
||||
const approvePermission = resolveEntityPermission(task.workflow_instance?.entity_type, "approve");
|
||||
if (approvePermission && hasPermission(request.employee.permissionCodes, approvePermission)) {
|
||||
actions.push("approve", "reject", "return");
|
||||
}
|
||||
|
||||
@@ -731,7 +732,7 @@ async function workflowRoutes(fastify) {
|
||||
fastify.post(
|
||||
"/workflow/tasks/:taskId/approve",
|
||||
{
|
||||
preHandler: fastify.requirePermission("expense.approve"),
|
||||
preHandler: fastify.authenticate,
|
||||
},
|
||||
async (request, reply) => {
|
||||
const taskId = parseTaskId(request.params?.taskId);
|
||||
@@ -744,6 +745,7 @@ async function workflowRoutes(fastify) {
|
||||
const assignment = await ensureTaskAssignableToCurrentEmployee(tx, task, request);
|
||||
|
||||
const workflowInstance = await loadWorkflowInstanceForTask(tx, task.instance_id);
|
||||
fastify.assertEntityPermission(request.employee, workflowInstance.entity_type, "approve");
|
||||
const steps = getWorkflowStepsSnapshot(workflowInstance);
|
||||
const currentStepIndex = steps.findIndex((step) => step.id === workflowInstance.current_step_id);
|
||||
if (currentStepIndex < 0) {
|
||||
@@ -966,7 +968,7 @@ async function workflowRoutes(fastify) {
|
||||
fastify.post(
|
||||
"/workflow/tasks/:taskId/reject",
|
||||
{
|
||||
preHandler: fastify.requirePermission("expense.approve"),
|
||||
preHandler: fastify.authenticate,
|
||||
},
|
||||
async (request, reply) => {
|
||||
const taskId = parseTaskId(request.params?.taskId);
|
||||
@@ -980,6 +982,7 @@ async function workflowRoutes(fastify) {
|
||||
const assignment = await ensureTaskAssignableToCurrentEmployee(tx, task, request);
|
||||
|
||||
const workflowInstance = await loadWorkflowInstanceForTask(tx, task.instance_id);
|
||||
fastify.assertEntityPermission(request.employee, workflowInstance.entity_type, "approve");
|
||||
const now = new Date();
|
||||
|
||||
await tx.workflowTask.update({
|
||||
@@ -1095,7 +1098,7 @@ async function workflowRoutes(fastify) {
|
||||
fastify.post(
|
||||
"/workflow/tasks/:taskId/return",
|
||||
{
|
||||
preHandler: fastify.requirePermission("expense.approve"),
|
||||
preHandler: fastify.authenticate,
|
||||
},
|
||||
async (request, reply) => {
|
||||
const taskId = parseTaskId(request.params?.taskId);
|
||||
@@ -1109,6 +1112,7 @@ async function workflowRoutes(fastify) {
|
||||
const assignment = await ensureTaskAssignableToCurrentEmployee(tx, task, request);
|
||||
|
||||
const workflowInstance = await loadWorkflowInstanceForTask(tx, task.instance_id);
|
||||
fastify.assertEntityPermission(request.employee, workflowInstance.entity_type, "approve");
|
||||
const now = new Date();
|
||||
|
||||
await tx.workflowTask.update({
|
||||
@@ -1353,3 +1357,7 @@ async function workflowRoutes(fastify) {
|
||||
}
|
||||
|
||||
module.exports = workflowRoutes;
|
||||
|
||||
module.exports.__testables = {
|
||||
listAllowedActionsForTask,
|
||||
};
|
||||
|
||||
在新工单中引用
屏蔽一个用户