mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-05 09:26:37 +00:00
Refactor approval URL construction in access and secret approval request services
- Updated the construction of approval URLs to use a consistent project path format. - Modified notification payloads to include the new approval URL structure. - Enhanced Slack message formatting to include buttons for viewing requests directly.
This commit is contained in:
@@ -399,7 +399,8 @@ export const accessApprovalRequestServiceFactory = ({
|
|||||||
|
|
||||||
const requesterFullName = `${requestedByUser.firstName} ${requestedByUser.lastName}`;
|
const requesterFullName = `${requestedByUser.firstName} ${requestedByUser.lastName}`;
|
||||||
const editorFullName = `${editedByUser.firstName} ${editedByUser.lastName}`;
|
const editorFullName = `${editedByUser.firstName} ${editedByUser.lastName}`;
|
||||||
const approvalPath = `/projects/secret-management/${project.id}/approval`;
|
const projectPath = `/projects/secret-management/${project.id}`;
|
||||||
|
const approvalPath = `${projectPath}/approval`;
|
||||||
const approvalUrl = `${cfg.SITE_URL}${approvalPath}`;
|
const approvalUrl = `${cfg.SITE_URL}${approvalPath}`;
|
||||||
|
|
||||||
await triggerWorkflowIntegrationNotification({
|
await triggerWorkflowIntegrationNotification({
|
||||||
@@ -417,7 +418,8 @@ export const accessApprovalRequestServiceFactory = ({
|
|||||||
approvalUrl,
|
approvalUrl,
|
||||||
editNote,
|
editNote,
|
||||||
editorEmail: editedByUser.email as string,
|
editorEmail: editedByUser.email as string,
|
||||||
editorFullName
|
editorFullName,
|
||||||
|
projectPath
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
projectId: project.id
|
projectId: project.id
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ export const sendApprovalEmailsFn = async ({
|
|||||||
type: NotificationType.SECRET_CHANGE_REQUEST,
|
type: NotificationType.SECRET_CHANGE_REQUEST,
|
||||||
title: "Secret Change Request",
|
title: "Secret Change Request",
|
||||||
body: `You have a new secret change request pending your review for the project **${project.name}** in the organization **${project.organization.name}**.`,
|
body: `You have a new secret change request pending your review for the project **${project.name}** in the organization **${project.organization.name}**.`,
|
||||||
link: `/projects/secret-management/${project.id}/approval?requestId=${secretApprovalRequest.id}`
|
link: `/projects/secret-management/${project.id}/approval`
|
||||||
}))
|
}))
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -51,7 +51,7 @@ export const sendApprovalEmailsFn = async ({
|
|||||||
firstName: reviewerUser.firstName,
|
firstName: reviewerUser.firstName,
|
||||||
projectName: project.name,
|
projectName: project.name,
|
||||||
organizationName: project.organization.name,
|
organizationName: project.organization.name,
|
||||||
approvalUrl: `${cfg.SITE_URL}/projects/secret-management/${project.id}/approval?requestId=${secretApprovalRequest.id}`
|
approvalUrl: `${cfg.SITE_URL}/projects/secret-management/${project.id}/approval}`
|
||||||
},
|
},
|
||||||
template: SmtpTemplates.SecretApprovalRequestNeedsReview
|
template: SmtpTemplates.SecretApprovalRequestNeedsReview
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1416,6 +1416,11 @@ export const secretApprovalRequestServiceFactory = ({
|
|||||||
const env = await projectEnvDAL.findOne({ id: policy.envId });
|
const env = await projectEnvDAL.findOne({ id: policy.envId });
|
||||||
const user = await userDAL.findById(actorId);
|
const user = await userDAL.findById(actorId);
|
||||||
|
|
||||||
|
const projectPath = `/projects/secret-management/${projectId}`;
|
||||||
|
const approvalPath = `${projectPath}/approval`;
|
||||||
|
const cfg = getConfig();
|
||||||
|
const approvalUrl = `${cfg.SITE_URL}${approvalPath}`;
|
||||||
|
|
||||||
await triggerWorkflowIntegrationNotification({
|
await triggerWorkflowIntegrationNotification({
|
||||||
input: {
|
input: {
|
||||||
projectId,
|
projectId,
|
||||||
@@ -1427,7 +1432,8 @@ export const secretApprovalRequestServiceFactory = ({
|
|||||||
secretPath,
|
secretPath,
|
||||||
projectId,
|
projectId,
|
||||||
requestId: secretApprovalRequest.id,
|
requestId: secretApprovalRequest.id,
|
||||||
secretKeys: [...new Set(Object.values(data).flatMap((arr) => arr?.map((item) => item.secretName) ?? []))]
|
secretKeys: [...new Set(Object.values(data).flatMap((arr) => arr?.map((item) => item.secretName) ?? []))],
|
||||||
|
approvalUrl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -1786,6 +1792,11 @@ export const secretApprovalRequestServiceFactory = ({
|
|||||||
const user = await userDAL.findById(actorId);
|
const user = await userDAL.findById(actorId);
|
||||||
const env = await projectEnvDAL.findOne({ id: policy.envId });
|
const env = await projectEnvDAL.findOne({ id: policy.envId });
|
||||||
|
|
||||||
|
const projectPath = `/projects/secret-management/${project.id}`;
|
||||||
|
const approvalPath = `${projectPath}/approval`;
|
||||||
|
const cfg = getConfig();
|
||||||
|
const approvalUrl = `${cfg.SITE_URL}${approvalPath}`;
|
||||||
|
|
||||||
await triggerWorkflowIntegrationNotification({
|
await triggerWorkflowIntegrationNotification({
|
||||||
input: {
|
input: {
|
||||||
projectId,
|
projectId,
|
||||||
@@ -1797,7 +1808,8 @@ export const secretApprovalRequestServiceFactory = ({
|
|||||||
secretPath,
|
secretPath,
|
||||||
projectId,
|
projectId,
|
||||||
requestId: secretApprovalRequest.id,
|
requestId: secretApprovalRequest.id,
|
||||||
secretKeys: [...new Set(Object.values(data).flatMap((arr) => arr?.map((item) => item.secretKey) ?? []))]
|
secretKeys: [...new Set(Object.values(data).flatMap((arr) => arr?.map((item) => item.secretKey) ?? []))],
|
||||||
|
approvalUrl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ export type TNotification =
|
|||||||
requestId: string;
|
requestId: string;
|
||||||
projectId: string;
|
projectId: string;
|
||||||
secretKeys: string[];
|
secretKeys: string[];
|
||||||
|
approvalUrl: string;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
| {
|
| {
|
||||||
@@ -52,6 +53,7 @@ export type TNotification =
|
|||||||
editNote?: string;
|
editNote?: string;
|
||||||
editorFullName?: string;
|
editorFullName?: string;
|
||||||
editorEmail?: string;
|
editorEmail?: string;
|
||||||
|
projectPath: string;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
| {
|
| {
|
||||||
|
|||||||
@@ -51,13 +51,9 @@ const buildSlackPayload = (notification: TNotification) => {
|
|||||||
const messageBody = `A secret approval request has been opened by ${payload.userEmail}.
|
const messageBody = `A secret approval request has been opened by ${payload.userEmail}.
|
||||||
*Environment*: ${payload.environment}
|
*Environment*: ${payload.environment}
|
||||||
*Secret path*: ${payload.secretPath || "/"}
|
*Secret path*: ${payload.secretPath || "/"}
|
||||||
*Secret Key${payload.secretKeys.length > 1 ? "s" : ""}*: ${payload.secretKeys.join(", ")}
|
*Secret Key${payload.secretKeys.length > 1 ? "s" : ""}*: ${payload.secretKeys.join(", ")}`;
|
||||||
|
|
||||||
View the complete details <${appCfg.SITE_URL}/projects/secret-management/${payload.projectId}/approval?requestId=${
|
const headerBlocks = [
|
||||||
payload.requestId
|
|
||||||
}|here>.`;
|
|
||||||
|
|
||||||
const payloadBlocks = [
|
|
||||||
{
|
{
|
||||||
type: "header",
|
type: "header",
|
||||||
text: {
|
text: {
|
||||||
@@ -65,18 +61,36 @@ View the complete details <${appCfg.SITE_URL}/projects/secret-management/${paylo
|
|||||||
text: "Secret approval request",
|
text: "Secret approval request",
|
||||||
emoji: true
|
emoji: true
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
const payloadBlocks = [
|
||||||
{
|
{
|
||||||
type: "section",
|
type: "section",
|
||||||
text: {
|
text: {
|
||||||
type: "mrkdwn",
|
type: "mrkdwn",
|
||||||
text: messageBody
|
text: messageBody
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "actions",
|
||||||
|
elements: [
|
||||||
|
{
|
||||||
|
type: "button",
|
||||||
|
text: {
|
||||||
|
type: "plain_text",
|
||||||
|
text: "View request",
|
||||||
|
emoji: true
|
||||||
|
},
|
||||||
|
style: "primary",
|
||||||
|
url: payload.approvalUrl
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
headerBlocks: [],
|
headerBlocks,
|
||||||
payloadMessage: messageBody,
|
payloadMessage: messageBody,
|
||||||
payloadBlocks,
|
payloadBlocks,
|
||||||
color: COMPANY_BRAND_COLOR
|
color: COMPANY_BRAND_COLOR
|
||||||
@@ -84,12 +98,12 @@ View the complete details <${appCfg.SITE_URL}/projects/secret-management/${paylo
|
|||||||
}
|
}
|
||||||
case TriggerFeature.ACCESS_REQUEST: {
|
case TriggerFeature.ACCESS_REQUEST: {
|
||||||
const { payload } = notification;
|
const { payload } = notification;
|
||||||
const projectUrl = `${appCfg.SITE_URL}${payload.projectPath}`;
|
const projectUrl = `${appCfg.SITE_URL}${payload.projectPath}/overview`;
|
||||||
const accessType = payload.isTemporary ? "temporary" : "permanent";
|
const accessType = payload.isTemporary ? "temporary" : "permanent";
|
||||||
const permissionsFormatted = payload.permissions.map((p) => `*${p}*`).join(", ");
|
const permissionsFormatted = payload.permissions.map((p) => `*${p}*`).join(", ");
|
||||||
|
|
||||||
const messageBody = `${payload.requesterFullName} (${payload.requesterEmail}) has requested ${accessType} access to ${payload.secretPath} in the ${payload.environment} environment of ${payload.projectName}.\n\nThe following permissions are requested: ${payload.permissions.join(", ")}${
|
const messageBody = `${payload.requesterFullName} (${payload.requesterEmail}) has requested ${accessType} access to ${payload.secretPath} in the ${payload.environment} environment of ${payload.projectName}.\n\nThe following permissions are requested: ${payload.permissions.join(", ")}${
|
||||||
payload.note ? `\n\nUser note\n${payload.note}` : ""
|
payload.note ? `\n\nUser note: ${payload.note}` : ""
|
||||||
}`;
|
}`;
|
||||||
|
|
||||||
const headerBlocks = [
|
const headerBlocks = [
|
||||||
@@ -109,7 +123,7 @@ View the complete details <${appCfg.SITE_URL}/projects/secret-management/${paylo
|
|||||||
text: {
|
text: {
|
||||||
type: "mrkdwn",
|
type: "mrkdwn",
|
||||||
text: `*${payload.requesterFullName}* (${payload.requesterEmail}) has requested *${accessType}* access to *${payload.secretPath}* in the *${payload.environment}* environment of *<${projectUrl}|${payload.projectName}>*.\n\nThe following permissions are requested: ${permissionsFormatted}${
|
text: `*${payload.requesterFullName}* (${payload.requesterEmail}) has requested *${accessType}* access to *${payload.secretPath}* in the *${payload.environment}* environment of *<${projectUrl}|${payload.projectName}>*.\n\nThe following permissions are requested: ${permissionsFormatted}${
|
||||||
payload.note ? `\n\n*User note*\n${payload.note}` : ""
|
payload.note ? `\n\n*User note:* ${payload.note}` : ""
|
||||||
}`
|
}`
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -139,20 +153,15 @@ View the complete details <${appCfg.SITE_URL}/projects/secret-management/${paylo
|
|||||||
}
|
}
|
||||||
case TriggerFeature.ACCESS_REQUEST_UPDATED: {
|
case TriggerFeature.ACCESS_REQUEST_UPDATED: {
|
||||||
const { payload } = notification;
|
const { payload } = notification;
|
||||||
const messageBody = `${payload.editorFullName} (${payload.editorEmail}) has updated the ${
|
const projectUrl = `${appCfg.SITE_URL}${payload.projectPath}/overview`;
|
||||||
payload.isTemporary ? "temporary" : "permanent"
|
const accessType = payload.isTemporary ? "temporary" : "permanent";
|
||||||
} access request from ${payload.requesterFullName} (${payload.requesterEmail}) to ${payload.secretPath} in the ${payload.environment} environment of ${payload.projectName}.
|
const permissionsFormatted = payload.permissions.map((p) => `*${p}*`).join(", ");
|
||||||
|
|
||||||
The following permissions are requested: ${payload.permissions.join(", ")}
|
const messageBody = `${payload.editorFullName} (${payload.editorEmail}) has updated the ${accessType} access request from ${payload.requesterFullName} (${payload.requesterEmail}) to ${payload.secretPath} in the ${payload.environment} environment of ${payload.projectName}.\n\nThe following permissions are requested: ${payload.permissions.join(", ")}${
|
||||||
|
payload.editNote ? `\n\nEditor Note: ${payload.editNote}` : ""
|
||||||
View the request and approve or deny it <${payload.approvalUrl}|here>.${
|
|
||||||
payload.editNote
|
|
||||||
? `
|
|
||||||
Editor Note: ${payload.editNote}`
|
|
||||||
: ""
|
|
||||||
}`;
|
}`;
|
||||||
|
|
||||||
const payloadBlocks = [
|
const headerBlocks = [
|
||||||
{
|
{
|
||||||
type: "header",
|
type: "header",
|
||||||
text: {
|
text: {
|
||||||
@@ -160,18 +169,38 @@ Editor Note: ${payload.editNote}`
|
|||||||
text: "Updated access approval request pending for review",
|
text: "Updated access approval request pending for review",
|
||||||
emoji: true
|
emoji: true
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
const payloadBlocks = [
|
||||||
{
|
{
|
||||||
type: "section",
|
type: "section",
|
||||||
text: {
|
text: {
|
||||||
type: "mrkdwn",
|
type: "mrkdwn",
|
||||||
text: messageBody
|
text: `*${payload.editorFullName}* (${payload.editorEmail}) has updated the *${accessType}* access request from *${payload.requesterFullName}* (${payload.requesterEmail}) to *${payload.secretPath}* in the *${payload.environment}* environment of *<${projectUrl}|${payload.projectName}>*.\n\nThe following permissions are requested: ${permissionsFormatted}${
|
||||||
|
payload.editNote ? `\n\n*Editor Note:* ${payload.editNote}` : ""
|
||||||
|
}`
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "actions",
|
||||||
|
elements: [
|
||||||
|
{
|
||||||
|
type: "button",
|
||||||
|
text: {
|
||||||
|
type: "plain_text",
|
||||||
|
text: "View request",
|
||||||
|
emoji: true
|
||||||
|
},
|
||||||
|
style: "primary",
|
||||||
|
url: payload.approvalUrl
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
headerBlocks: [],
|
headerBlocks,
|
||||||
payloadMessage: messageBody,
|
payloadMessage: messageBody,
|
||||||
payloadBlocks,
|
payloadBlocks,
|
||||||
color: COMPANY_BRAND_COLOR
|
color: COMPANY_BRAND_COLOR
|
||||||
@@ -198,7 +227,7 @@ Editor Note: ${payload.editNote}`
|
|||||||
type: "section",
|
type: "section",
|
||||||
text: {
|
text: {
|
||||||
type: "mrkdwn",
|
type: "mrkdwn",
|
||||||
text: `*Environment*\n${payload.environment}\n\n\n*Secret Path*\n${payload.secretPath}\n\n\n*Project*\n<${projectUrl}|${payload.projectName}>\n\n\n*Reason*\n${payload.failureMessage}`
|
text: `*Environment:* ${payload.environment}\n\n*Secret Path:* ${payload.secretPath}\n\n*Project:* <${projectUrl}|${payload.projectName}>\n\n*Reason:* ${payload.failureMessage}`
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user