FIX - МЕЖПРОЕКТНАЯ КОММУНИКАЦИЯ: автоподтверждение повторных workspace-инвайтов
This commit is contained in:
parent
0ba6dc7115
commit
784195f747
|
|
@ -892,6 +892,8 @@ export function createControlPlaneStore({ projectRoot }) {
|
|||
const workspaceName = optionalString(payload?.workspaceName, workspaceSlug);
|
||||
const inviteeEmail = requireString(payload?.inviteeEmail, "inviteeEmail").toLowerCase();
|
||||
const role = normalizeTaskManagerInviteRole(payload?.role);
|
||||
const inviteeUser = data.users.find((user) => user.email.toLowerCase() === inviteeEmail && user.globalStatus === "active");
|
||||
const autoApproveExistingUser = Boolean(inviteeUser && !hasTaskManagerDenyException(data, inviteeUser.id));
|
||||
const existingRequest = data.taskerInviteRequests.find(
|
||||
(request) =>
|
||||
request.taskerInviteId === taskerInviteId ||
|
||||
|
|
@ -904,6 +906,18 @@ export function createControlPlaneStore({ projectRoot }) {
|
|||
taskerInviteId,
|
||||
createdAt: now,
|
||||
};
|
||||
let nextStatus = "new";
|
||||
if (existingRequest?.status && existingRequest.status !== "rejected") {
|
||||
nextStatus = existingRequest.status;
|
||||
}
|
||||
if (autoApproveExistingUser) {
|
||||
nextStatus = "approved";
|
||||
}
|
||||
|
||||
let auditAction = existingRequest ? "Обновлена заявка workspace-инвайта" : "Создана заявка workspace-инвайта";
|
||||
if (autoApproveExistingUser) {
|
||||
auditAction = "Автоподтверждена заявка workspace-инвайта";
|
||||
}
|
||||
|
||||
Object.assign(request, {
|
||||
taskerInviteId,
|
||||
|
|
@ -916,11 +930,13 @@ export function createControlPlaneStore({ projectRoot }) {
|
|||
inviterPlaneUserId: nullableStringWithFallback(payload?.inviterPlaneUserId, request.inviterPlaneUserId ?? null),
|
||||
inviterEmail: requireString(payload?.inviterEmail, "inviterEmail").toLowerCase(),
|
||||
inviterName: optionalString(payload?.inviterName, payload?.inviterEmail ?? "Operational Core user"),
|
||||
status: existingRequest?.status && existingRequest.status !== "rejected" ? existingRequest.status : "new",
|
||||
status: nextStatus,
|
||||
taskerInviteLink: existingRequest?.taskerInviteLink ?? null,
|
||||
reviewedByUserId: existingRequest?.reviewedByUserId ?? null,
|
||||
reviewedAt: existingRequest?.reviewedAt ?? null,
|
||||
comment: nullableStringWithFallback(payload?.comment, existingRequest?.comment ?? null),
|
||||
reviewedByUserId: autoApproveExistingUser ? actor.id : existingRequest?.reviewedByUserId ?? null,
|
||||
reviewedAt: autoApproveExistingUser ? now : existingRequest?.reviewedAt ?? null,
|
||||
comment: autoApproveExistingUser
|
||||
? "Автоподтверждено: пользователь уже активен в NODE.DC."
|
||||
: nullableStringWithFallback(payload?.comment, existingRequest?.comment ?? null),
|
||||
updatedAt: now,
|
||||
});
|
||||
|
||||
|
|
@ -928,8 +944,20 @@ export function createControlPlaneStore({ projectRoot }) {
|
|||
data.taskerInviteRequests.push(request);
|
||||
}
|
||||
|
||||
if (autoApproveExistingUser && inviteeUser) {
|
||||
ensureTaskerInviteServiceAccess(
|
||||
data,
|
||||
{
|
||||
source: "tasker_workspace_invite",
|
||||
sourceTaskerInviteRequestId: request.id,
|
||||
},
|
||||
inviteeUser,
|
||||
now
|
||||
);
|
||||
}
|
||||
|
||||
addAuditEvent(data, actor, {
|
||||
action: existingRequest ? "Обновлена заявка workspace-инвайта" : "Создана заявка workspace-инвайта",
|
||||
action: auditAction,
|
||||
objectType: "tasker_invite_request",
|
||||
objectName: `${workspaceSlug}:${inviteeEmail}`,
|
||||
result: "success",
|
||||
|
|
@ -937,7 +965,12 @@ export function createControlPlaneStore({ projectRoot }) {
|
|||
});
|
||||
|
||||
await writeData(data);
|
||||
return { taskerInviteRequest: request, data };
|
||||
return {
|
||||
taskerInviteRequest: request,
|
||||
autoApproved: autoApproveExistingUser,
|
||||
affectedUserIds: [payload?.inviterUserId, inviteeUser?.id].filter((userId) => typeof userId === "string" && userId),
|
||||
data,
|
||||
};
|
||||
}
|
||||
|
||||
async function approveTaskerInviteRequest(taskerInviteRequestId, payload, identity) {
|
||||
|
|
@ -2295,6 +2328,17 @@ function ensureTaskerInviteServiceAccess(data, invite, user, now) {
|
|||
return grant;
|
||||
}
|
||||
|
||||
function hasTaskManagerDenyException(data, userId) {
|
||||
const service = data.services.find((candidate) => candidate.slug === "task-manager");
|
||||
if (!service) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return data.exceptions.some(
|
||||
(exception) => exception.serviceId === service.id && exception.userId === userId && exception.type === "deny"
|
||||
);
|
||||
}
|
||||
|
||||
function findTaskerInviteRequestForCancellation(data, payload) {
|
||||
const requestId = nullableString(payload?.requestId);
|
||||
const taskerInviteId = nullableString(payload?.taskerInviteId);
|
||||
|
|
|
|||
|
|
@ -501,8 +501,11 @@ app.post("/api/internal/tasker/invite-requests", asyncRoute(async (req, res) =>
|
|||
inviterName: inviter.name,
|
||||
}, inviter);
|
||||
|
||||
publishControlPlaneEvent("tasker.invite-request.created", [inviter.id]);
|
||||
res.json({ ok: true, taskerInviteRequest: result.taskerInviteRequest });
|
||||
publishControlPlaneEvent(
|
||||
"tasker.invite-request.created",
|
||||
result.affectedUserIds?.length ? result.affectedUserIds : [inviter.id]
|
||||
);
|
||||
res.json({ ok: true, taskerInviteRequest: result.taskerInviteRequest, autoApproved: Boolean(result.autoApproved) });
|
||||
}));
|
||||
|
||||
app.post("/api/internal/tasker/invite-requests/cancel", asyncRoute(async (req, res) => {
|
||||
|
|
|
|||
Loading…
Reference in New Issue