mirror of
https://github.com/Infisical/infisical.git
synced 2026-01-08 15:13:55 -05:00
fix: review comments
This commit is contained in:
@@ -14,44 +14,35 @@ export const scimDALFactory = (db: TDbClient) => {
|
||||
|
||||
const findExpiringTokens = async (tx?: Knex, batchSize = 500, offset = 0): Promise<TExpiringScimToken[]> => {
|
||||
try {
|
||||
const conn = tx || db.replicaNode();
|
||||
|
||||
const batch = await conn(TableName.ScimToken)
|
||||
.join(TableName.Organization, `${TableName.Organization}.id`, `${TableName.ScimToken}.orgId`)
|
||||
const batch = await (tx || db.replicaNode())(TableName.ScimToken)
|
||||
.leftJoin(TableName.Organization, `${TableName.Organization}.id`, `${TableName.ScimToken}.orgId`)
|
||||
.leftJoin(TableName.Membership, `${TableName.Membership}.scopeOrgId`, `${TableName.ScimToken}.orgId`)
|
||||
.leftJoin(TableName.MembershipRole, `${TableName.MembershipRole}.membershipId`, `${TableName.Membership}.id`)
|
||||
.leftJoin(TableName.Users, `${TableName.Users}.id`, `${TableName.Membership}.actorUserId`)
|
||||
.whereRaw(
|
||||
`
|
||||
(${TableName.ScimToken}."ttlDays" > 0 AND
|
||||
(${TableName.ScimToken}."createdAt" + INTERVAL '1 day' * ${TableName.ScimToken}."ttlDays") < NOW() + INTERVAL '1 day' AND
|
||||
(${TableName.ScimToken}."createdAt" + INTERVAL '1 day' * ${TableName.ScimToken}."ttlDays") > NOW())
|
||||
(${TableName.ScimToken}."createdAt" + INTERVAL '1 day' * ${TableName.ScimToken}."ttlDays") < NOW() + INTERVAL '7 days' AND
|
||||
(${TableName.ScimToken}."createdAt" + INTERVAL '1 day' * ${TableName.ScimToken}."ttlDays") > NOW())
|
||||
`
|
||||
)
|
||||
.where(`${TableName.ScimToken}.expiryNotificationSent`, false)
|
||||
.select<TExpiringScimToken[]>(
|
||||
conn.ref("id").withSchema(TableName.ScimToken),
|
||||
conn.ref("ttlDays").withSchema(TableName.ScimToken),
|
||||
conn.ref("description").withSchema(TableName.ScimToken),
|
||||
conn.ref("orgId").withSchema(TableName.ScimToken),
|
||||
conn.ref("createdAt").withSchema(TableName.ScimToken),
|
||||
conn.ref("name").withSchema(TableName.Organization).as("orgName"),
|
||||
conn.raw(`
|
||||
COALESCE(
|
||||
(
|
||||
SELECT array_agg(${TableName.Users}.email)
|
||||
FROM ${TableName.Membership}
|
||||
JOIN ${TableName.MembershipRole} ON ${TableName.Membership}.id = ${TableName.MembershipRole}."membershipId"
|
||||
JOIN ${TableName.Users} ON ${TableName.Membership}."actorUserId" = ${TableName.Users}.id
|
||||
WHERE ${TableName.Membership}."scopeOrgId" = ${TableName.ScimToken}."orgId"
|
||||
AND ${TableName.Membership}.scope = '${AccessScope.Organization}'
|
||||
AND ${TableName.MembershipRole}.role = '${OrgMembershipRole.Admin}'
|
||||
AND ${TableName.Membership}.status != '${OrgMembershipStatus.Invited}'
|
||||
AND ${TableName.Membership}."actorUserId" IS NOT NULL
|
||||
AND ${TableName.Users}."isGhost" = false
|
||||
AND ${TableName.Users}.email IS NOT NULL
|
||||
),
|
||||
ARRAY[]::text[]
|
||||
) as "adminEmails"
|
||||
`)
|
||||
)
|
||||
.where(`${TableName.Membership}.scope`, AccessScope.Organization)
|
||||
.where(`${TableName.MembershipRole}.role`, OrgMembershipRole.Admin)
|
||||
.whereNot(`${TableName.Membership}.status`, OrgMembershipStatus.Invited)
|
||||
.whereNotNull(`${TableName.Membership}.actorUserId`)
|
||||
.where(`${TableName.Users}.isGhost`, false)
|
||||
.whereNotNull(`${TableName.Users}.email`)
|
||||
.groupBy([`${TableName.ScimToken}.id`, `${TableName.Organization}.name`])
|
||||
.select<TExpiringScimToken[]>([
|
||||
db.ref("id").withSchema(TableName.ScimToken),
|
||||
db.ref("ttlDays").withSchema(TableName.ScimToken),
|
||||
db.ref("description").withSchema(TableName.ScimToken),
|
||||
db.ref("orgId").withSchema(TableName.ScimToken),
|
||||
db.ref("createdAt").withSchema(TableName.ScimToken),
|
||||
db.ref("name").withSchema(TableName.Organization).as("orgName"),
|
||||
db.raw(`array_agg(${TableName.Users}."email") as "adminEmails"`)
|
||||
])
|
||||
.limit(batchSize)
|
||||
.offset(offset);
|
||||
|
||||
|
||||
@@ -1266,6 +1266,9 @@ export const scimServiceFactory = ({
|
||||
return;
|
||||
}
|
||||
|
||||
const createdOn = new Date(token.createdAt);
|
||||
const expiringOn = new Date(createdOn.getTime() + Number(token.ttlDays) * 86400 * 1000);
|
||||
|
||||
await smtpService.sendMail({
|
||||
recipients: token.adminEmails,
|
||||
subjectLine: "SCIM Token Expiry Notice",
|
||||
@@ -1273,7 +1276,9 @@ export const scimServiceFactory = ({
|
||||
substitutions: {
|
||||
tokenDescription: token.description,
|
||||
orgName: token.orgName,
|
||||
url: `${appCfg.SITE_URL}/organizations/${token.orgId}/settings?selectedTab=provisioning-settings`
|
||||
url: `${appCfg.SITE_URL}/organizations/${token.orgId}/settings?selectedTab=provisioning-settings`,
|
||||
createdOn,
|
||||
expiringOn
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -7,6 +7,8 @@ import { BaseEmailWrapper, BaseEmailWrapperProps } from "./BaseEmailWrapper";
|
||||
interface ScimTokenExpiryNoticeTemplateProps extends Omit<BaseEmailWrapperProps, "title" | "preview" | "children"> {
|
||||
tokenDescription?: string;
|
||||
orgName: string;
|
||||
createdOn: Date;
|
||||
expiringOn: Date;
|
||||
url: string;
|
||||
}
|
||||
|
||||
@@ -14,8 +16,20 @@ export const ScimTokenExpiryNoticeTemplate = ({
|
||||
tokenDescription,
|
||||
siteUrl,
|
||||
orgName,
|
||||
url
|
||||
url,
|
||||
createdOn,
|
||||
expiringOn
|
||||
}: ScimTokenExpiryNoticeTemplateProps) => {
|
||||
const formatDate = (date: Date) =>
|
||||
date.toLocaleDateString("en-US", {
|
||||
year: "numeric",
|
||||
month: "long",
|
||||
day: "numeric"
|
||||
});
|
||||
|
||||
const createdOnDisplay = formatDate(createdOn);
|
||||
const expiringOnDisplay = formatDate(expiringOn);
|
||||
|
||||
return (
|
||||
<BaseEmailWrapper title="SCIM Token Expiring Soon" preview="A SCIM token is about to expire." siteUrl={siteUrl}>
|
||||
<Heading className="text-black text-[18px] leading-[28px] text-center font-normal p-0 mx-0">
|
||||
@@ -30,7 +44,8 @@ export const ScimTokenExpiryNoticeTemplate = ({
|
||||
) : (
|
||||
"One of your SCIM tokens"
|
||||
)}{" "}
|
||||
for the organization <strong>{orgName}</strong> will expire within 24 hours.
|
||||
for <strong>{orgName}</strong>, created on <strong>{createdOnDisplay}</strong>, is scheduled to expire on{" "}
|
||||
<strong>{expiringOnDisplay}</strong>.
|
||||
</Text>
|
||||
<Text>
|
||||
If this token is still needed for your external platform sync, please create a new one before it expires to
|
||||
@@ -50,5 +65,7 @@ ScimTokenExpiryNoticeTemplate.PreviewProps = {
|
||||
orgName: "Example Organization",
|
||||
siteUrl: "https://infisical.com",
|
||||
url: "https://infisical.com",
|
||||
tokenDescription: "Example SCIM Token"
|
||||
tokenDescription: "Example SCIM Token",
|
||||
createdOn: new Date("2025-11-27T00:00:00Z"),
|
||||
expiringOn: new Date("2025-12-27T00:00:00Z")
|
||||
} as ScimTokenExpiryNoticeTemplateProps;
|
||||
|
||||
Reference in New Issue
Block a user