diff --git a/backend/src/@types/fastify.d.ts b/backend/src/@types/fastify.d.ts index 30bdc7112..d511187d0 100644 --- a/backend/src/@types/fastify.d.ts +++ b/backend/src/@types/fastify.d.ts @@ -32,6 +32,7 @@ import { TPamResourceServiceFactory } from "@app/ee/services/pam-resource/pam-re import { TPamSessionServiceFactory } from "@app/ee/services/pam-session/pam-session-service"; import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types"; import { TPitServiceFactory } from "@app/ee/services/pit/pit-service"; +import { TPkiAcmeServiceFactory } from "@app/ee/services/pki-acme/pki-acme-types"; import { TProjectTemplateServiceFactory } from "@app/ee/services/project-template/project-template-types"; import { RateLimitConfiguration, TRateLimitServiceFactory } from "@app/ee/services/rate-limit/rate-limit-types"; import { TRelayServiceFactory } from "@app/ee/services/relay/relay-service"; @@ -106,7 +107,6 @@ import { TPkiCollectionServiceFactory } from "@app/services/pki-collection/pki-c import { TPkiSubscriberServiceFactory } from "@app/services/pki-subscriber/pki-subscriber-service"; import { TPkiSyncServiceFactory } from "@app/services/pki-sync/pki-sync-service"; import { TPkiTemplatesServiceFactory } from "@app/services/pki-templates/pki-templates-service"; -import { TPkiAcmeServiceFactory } from "@app/ee/services/pki-acme/pki-acme-types"; import { TProjectServiceFactory } from "@app/services/project/project-service"; import { TProjectBotServiceFactory } from "@app/services/project-bot/project-bot-service"; import { TProjectEnvServiceFactory } from "@app/services/project-env/project-env-service"; diff --git a/backend/src/db/migrations/20251104234547_add-pki-acme.ts b/backend/src/db/migrations/20251104234547_add-pki-acme.ts index c6b95009b..9dff45ccb 100644 --- a/backend/src/db/migrations/20251104234547_add-pki-acme.ts +++ b/backend/src/db/migrations/20251104234547_add-pki-acme.ts @@ -1,7 +1,9 @@ import { Knex } from "knex"; + +import { dropConstraintIfExists } from "@app/db/migrations/utils/dropConstraintIfExists"; + import { TableName } from "../schemas"; import { createOnUpdateTrigger, dropOnUpdateTrigger } from "../utils"; -import { dropConstraintIfExists } from "@app/db/migrations/utils/dropConstraintIfExists"; // Notice: the old constraint name is "enrollmentType_check" instead of "enrollment_type_check" // with psql, if there's no quote around an identifier, it will be lowercased. diff --git a/backend/src/ee/routes/v1/index.ts b/backend/src/ee/routes/v1/index.ts index e104a8355..ce05ea3b6 100644 --- a/backend/src/ee/routes/v1/index.ts +++ b/backend/src/ee/routes/v1/index.ts @@ -1,6 +1,6 @@ import { registerProjectTemplateRouter } from "@app/ee/routes/v1/project-template-router"; - import { getConfig } from "@app/lib/config/env"; + import { registerAccessApprovalPolicyRouter } from "./access-approval-policy-router"; import { registerAccessApprovalRequestRouter } from "./access-approval-request-router"; import { registerAssumePrivilegeRouter } from "./assume-privilege-router"; diff --git a/backend/src/ee/routes/v1/pki-acme-router.ts b/backend/src/ee/routes/v1/pki-acme-router.ts index b1419c086..627537c44 100644 --- a/backend/src/ee/routes/v1/pki-acme-router.ts +++ b/backend/src/ee/routes/v1/pki-acme-router.ts @@ -1,5 +1,4 @@ /* eslint-disable @typescript-eslint/no-floating-promises */ -import type { TAcmeResponse, TAuthenciatedJwsPayload, TRawJwsPayload } from "@app/ee/services/pki-acme/pki-acme-types"; import { FastifyReply, FastifyRequest } from "fastify"; import { z } from "zod"; @@ -19,6 +18,7 @@ import { RespondToAcmeChallengeBodySchema, RespondToAcmeChallengeResponseSchema } from "@app/ee/services/pki-acme/pki-acme-schemas"; +import type { TAcmeResponse, TAuthenciatedJwsPayload, TRawJwsPayload } from "@app/ee/services/pki-acme/pki-acme-types"; import { ApiDocsTags } from "@app/lib/api-docs"; import { readLimit, writeLimit } from "@app/server/config/rateLimiter"; diff --git a/backend/src/ee/routes/v1/secret-approval-request-router.ts b/backend/src/ee/routes/v1/secret-approval-request-router.ts index 78d9aeddc..bd5bacc5f 100644 --- a/backend/src/ee/routes/v1/secret-approval-request-router.ts +++ b/backend/src/ee/routes/v1/secret-approval-request-router.ts @@ -315,6 +315,7 @@ export const registerSecretApprovalRequestRouter = async (server: FastifyZodProv .extend({ status: z.string(), comment: z.string().optional(), + createdAt: z.date(), isOrgMembershipActive: z.boolean().nullable().optional() }) .array(), diff --git a/backend/src/ee/services/pki-acme/pki-acme-challenge-dal.ts b/backend/src/ee/services/pki-acme/pki-acme-challenge-dal.ts index 948f4af6e..74cbd1466 100644 --- a/backend/src/ee/services/pki-acme/pki-acme-challenge-dal.ts +++ b/backend/src/ee/services/pki-acme/pki-acme-challenge-dal.ts @@ -1,8 +1,10 @@ +import { Knex } from "knex"; + import { TDbClient } from "@app/db"; import { TableName, TPkiAcmeChallenges } from "@app/db/schemas"; import { DatabaseError } from "@app/lib/errors"; import { ormify, selectAllTableCols } from "@app/lib/knex"; -import { Knex } from "knex"; + import { AcmeAuthStatus, AcmeChallengeStatus, AcmeOrderStatus } from "./pki-acme-schemas"; export type TPkiAcmeChallengeDALFactory = ReturnType; diff --git a/backend/src/ee/services/pki-acme/pki-acme-challenge-service.ts b/backend/src/ee/services/pki-acme/pki-acme-challenge-service.ts index a058241c4..61bd0c110 100644 --- a/backend/src/ee/services/pki-acme/pki-acme-challenge-service.ts +++ b/backend/src/ee/services/pki-acme/pki-acme-challenge-service.ts @@ -2,6 +2,7 @@ import { getConfig } from "@app/lib/config/env"; import { BadRequestError, NotFoundError } from "@app/lib/errors"; import { isPrivateIp } from "@app/lib/ip/ipRange"; import { logger } from "@app/lib/logger"; + import { TPkiAcmeChallengeDALFactory } from "./pki-acme-challenge-dal"; import { AcmeConnectionError, diff --git a/backend/src/ee/services/pki-acme/pki-acme-fns.ts b/backend/src/ee/services/pki-acme/pki-acme-fns.ts index 0763a8ed0..828e0801b 100644 --- a/backend/src/ee/services/pki-acme/pki-acme-fns.ts +++ b/backend/src/ee/services/pki-acme/pki-acme-fns.ts @@ -1,5 +1,7 @@ -import { getConfig } from "@app/lib/config/env"; import { z } from "zod"; + +import { getConfig } from "@app/lib/config/env"; + import { AcmeMalformedError } from "./pki-acme-errors"; export const buildUrl = (profileId: string, path: string): string => { diff --git a/backend/src/ee/services/pki-acme/pki-acme-service.ts b/backend/src/ee/services/pki-acme/pki-acme-service.ts index e3a82000d..1e7123353 100644 --- a/backend/src/ee/services/pki-acme/pki-acme-service.ts +++ b/backend/src/ee/services/pki-acme/pki-acme-service.ts @@ -1,23 +1,4 @@ -import { TPkiAcmeAccounts } from "@app/db/schemas/pki-acme-accounts"; -import { TPkiAcmeAuths } from "@app/db/schemas/pki-acme-auths"; -import { crypto } from "@app/lib/crypto/cryptography"; -import { BadRequestError, NotFoundError, UnauthorizedError } from "@app/lib/errors"; -import { logger } from "@app/lib/logger"; -import { TCertificateProfileDALFactory } from "@app/services/certificate-profile/certificate-profile-dal"; import * as x509 from "@peculiar/x509"; - -import { KeyStorePrefixes, TKeyStoreFactory } from "@app/keystore/keystore"; -import { isPrivateIp } from "@app/lib/ip/ipRange"; -import { ActorType } from "@app/services/auth/auth-type"; -import { - EnrollmentType, - TCertificateProfileWithConfigs -} from "@app/services/certificate-profile/certificate-profile-types"; -import { TCertificateV3ServiceFactory } from "@app/services/certificate-v3/certificate-v3-service"; -import { TCertificateBodyDALFactory } from "@app/services/certificate/certificate-body-dal"; -import { TKmsServiceFactory } from "@app/services/kms/kms-service"; -import { TProjectDALFactory } from "@app/services/project/project-dal"; -import { getProjectKmsCertificateKeyId } from "@app/services/project/project-fns"; import { calculateJwkThumbprint, errors, @@ -27,6 +8,26 @@ import { JWSHeaderParameters } from "jose"; import { z, ZodError } from "zod"; + +import { TPkiAcmeAccounts } from "@app/db/schemas/pki-acme-accounts"; +import { TPkiAcmeAuths } from "@app/db/schemas/pki-acme-auths"; +import { KeyStorePrefixes, TKeyStoreFactory } from "@app/keystore/keystore"; +import { crypto } from "@app/lib/crypto/cryptography"; +import { BadRequestError, NotFoundError, UnauthorizedError } from "@app/lib/errors"; +import { isPrivateIp } from "@app/lib/ip/ipRange"; +import { logger } from "@app/lib/logger"; +import { ActorType } from "@app/services/auth/auth-type"; +import { TCertificateBodyDALFactory } from "@app/services/certificate/certificate-body-dal"; +import { TCertificateProfileDALFactory } from "@app/services/certificate-profile/certificate-profile-dal"; +import { + EnrollmentType, + TCertificateProfileWithConfigs +} from "@app/services/certificate-profile/certificate-profile-types"; +import { TCertificateV3ServiceFactory } from "@app/services/certificate-v3/certificate-v3-service"; +import { TKmsServiceFactory } from "@app/services/kms/kms-service"; +import { TProjectDALFactory } from "@app/services/project/project-dal"; +import { getProjectKmsCertificateKeyId } from "@app/services/project/project-fns"; + import { TPkiAcmeAccountDALFactory } from "./pki-acme-account-dal"; import { TPkiAcmeAuthDALFactory } from "./pki-acme-auth-dal"; import { TPkiAcmeChallengeDALFactory } from "./pki-acme-challenge-dal"; diff --git a/backend/src/ee/services/pki-acme/pki-acme-types.ts b/backend/src/ee/services/pki-acme/pki-acme-types.ts index 3132c9812..3ddb424f1 100644 --- a/backend/src/ee/services/pki-acme/pki-acme-types.ts +++ b/backend/src/ee/services/pki-acme/pki-acme-types.ts @@ -1,6 +1,6 @@ +import { JWSHeaderParameters } from "jose"; import { z } from "zod"; -import { JWSHeaderParameters } from "jose"; import { AcmeOrderResourceSchema, CreateAcmeAccountBodySchema, diff --git a/backend/src/ee/services/secret-approval-request/secret-approval-request-dal.ts b/backend/src/ee/services/secret-approval-request/secret-approval-request-dal.ts index db300720f..2610d9324 100644 --- a/backend/src/ee/services/secret-approval-request/secret-approval-request-dal.ts +++ b/backend/src/ee/services/secret-approval-request/secret-approval-request-dal.ts @@ -166,6 +166,7 @@ export const secretApprovalRequestDALFactory = (db: TDbClient) => { tx.ref("reviewerUserId").withSchema(TableName.SecretApprovalRequestReviewer), tx.ref("status").withSchema(TableName.SecretApprovalRequestReviewer).as("reviewerStatus"), tx.ref("comment").withSchema(TableName.SecretApprovalRequestReviewer).as("reviewerComment"), + tx.ref("createdAt").withSchema(TableName.SecretApprovalRequestReviewer).as("reviewerCreatedAt"), tx.ref("email").withSchema("secretApprovalReviewerUser").as("reviewerEmail"), tx.ref("username").withSchema("secretApprovalReviewerUser").as("reviewerUsername"), tx.ref("firstName").withSchema("secretApprovalReviewerUser").as("reviewerFirstName"), @@ -240,6 +241,7 @@ export const secretApprovalRequestDALFactory = (db: TDbClient) => { reviewerUsername: username, reviewerFirstName: firstName, reviewerComment: comment, + reviewerCreatedAt: createdAt, reviewerIsOrgMembershipActive: isOrgMembershipActive }) => userId @@ -251,6 +253,7 @@ export const secretApprovalRequestDALFactory = (db: TDbClient) => { lastName, username, comment: comment ?? "", + createdAt, isOrgMembershipActive } : undefined diff --git a/backend/src/server/routes/v3/certificates-router.ts b/backend/src/server/routes/v3/certificates-router.ts index 9aa4b198b..f590aa111 100644 --- a/backend/src/server/routes/v3/certificates-router.ts +++ b/backend/src/server/routes/v3/certificates-router.ts @@ -6,6 +6,12 @@ import { ms } from "@app/lib/ms"; import { writeLimit } from "@app/server/config/rateLimiter"; import { verifyAuth } from "@app/server/plugins/auth/verify-auth"; import { AuthMode } from "@app/services/auth/auth-type"; +import { + ACMESANType, + CertificateOrderStatus, + CertKeyAlgorithm, + CertSignatureAlgorithm +} from "@app/services/certificate/certificate-types"; import { validateCaDateField } from "@app/services/certificate-authority/certificate-authority-validators"; import { CertExtendedKeyUsageType, @@ -16,12 +22,6 @@ import { extractCertificateRequestFromCSR } from "@app/services/certificate-comm import { mapEnumsForValidation } from "@app/services/certificate-common/certificate-utils"; import { EnrollmentType } from "@app/services/certificate-profile/certificate-profile-types"; import { validateTemplateRegexField } from "@app/services/certificate-template/certificate-template-validators"; -import { - ACMESANType, - CertificateOrderStatus, - CertKeyAlgorithm, - CertSignatureAlgorithm -} from "@app/services/certificate/certificate-types"; interface CertificateRequestForService { commonName?: string; diff --git a/backend/src/services/certificate-v3/certificate-v3-service.test.ts b/backend/src/services/certificate-v3/certificate-v3-service.test.ts index 67c3b268b..6c664e324 100644 --- a/backend/src/services/certificate-v3/certificate-v3-service.test.ts +++ b/backend/src/services/certificate-v3/certificate-v3-service.test.ts @@ -7,6 +7,7 @@ import { ForbiddenError } from "@casl/ability"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types"; +import { TPkiAcmeAccountDALFactory } from "@app/ee/services/pki-acme/pki-acme-account-dal"; import { BadRequestError, ForbiddenRequestError, NotFoundError } from "@app/lib/errors"; import { TCertificateDALFactory } from "@app/services/certificate/certificate-dal"; import { TCertificateSecretDALFactory } from "@app/services/certificate/certificate-secret-dal"; @@ -30,7 +31,6 @@ import { extractCertificateRequestFromCSR } from "../certificate-common/certificate-csr-utils"; import { certificateV3ServiceFactory, TCertificateV3ServiceFactory } from "./certificate-v3-service"; -import { TPkiAcmeAccountDALFactory } from "@app/ee/services/pki-acme/pki-acme-account-dal"; vi.mock("../certificate-common/certificate-csr-utils", () => ({ extractCertificateRequestFromCSR: vi.fn(), diff --git a/backend/src/services/certificate-v3/certificate-v3-service.ts b/backend/src/services/certificate-v3/certificate-v3-service.ts index 6e505f338..bce5350c3 100644 --- a/backend/src/services/certificate-v3/certificate-v3-service.ts +++ b/backend/src/services/certificate-v3/certificate-v3-service.ts @@ -9,6 +9,7 @@ import { ProjectPermissionCertificateProfileActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission"; +import { TPkiAcmeAccountDALFactory } from "@app/ee/services/pki-acme/pki-acme-account-dal"; import { BadRequestError, ForbiddenRequestError, NotFoundError } from "@app/lib/errors"; import { ActorAuthMethod, ActorType } from "@app/services/auth/auth-type"; import { TCertificateDALFactory } from "@app/services/certificate/certificate-dal"; @@ -64,7 +65,6 @@ import { TSignCertificateFromProfileDTO, TUpdateRenewalConfigDTO } from "./certificate-v3-types"; -import { TPkiAcmeAccountDALFactory } from "@app/ee/services/pki-acme/pki-acme-account-dal"; type TCertificateV3ServiceFactoryDep = { certificateDAL: Pick; diff --git a/backend/src/services/certificate-v3/certificate-v3-types.ts b/backend/src/services/certificate-v3/certificate-v3-types.ts index 8685d5f30..8a2cf70f7 100644 --- a/backend/src/services/certificate-v3/certificate-v3-types.ts +++ b/backend/src/services/certificate-v3/certificate-v3-types.ts @@ -1,12 +1,12 @@ import { TProjectPermission } from "@app/lib/types"; +import { ACMESANType, CertificateOrderStatus } from "../certificate/certificate-types"; import { CertExtendedKeyUsageType, CertKeyUsageType, CertSubjectAlternativeNameType } from "../certificate-common/certificate-constants"; import { EnrollmentType } from "../certificate-profile/certificate-profile-types"; -import { ACMESANType, CertificateOrderStatus } from "../certificate/certificate-types"; export type TIssueCertificateFromProfileDTO = { profileId: string; diff --git a/backend/src/services/enrollment-config/enrollment-config-types.ts b/backend/src/services/enrollment-config/enrollment-config-types.ts index ed2f921c4..7fe5a475d 100644 --- a/backend/src/services/enrollment-config/enrollment-config-types.ts +++ b/backend/src/services/enrollment-config/enrollment-config-types.ts @@ -1,3 +1,8 @@ +import { + TPkiAcmeEnrollmentConfigs, + TPkiAcmeEnrollmentConfigsInsert, + TPkiAcmeEnrollmentConfigsUpdate +} from "@app/db/schemas/pki-acme-enrollment-configs"; import { TPkiApiEnrollmentConfigs, TPkiApiEnrollmentConfigsInsert, @@ -8,11 +13,6 @@ import { TPkiEstEnrollmentConfigsInsert, TPkiEstEnrollmentConfigsUpdate } from "@app/db/schemas/pki-est-enrollment-configs"; -import { - TPkiAcmeEnrollmentConfigs, - TPkiAcmeEnrollmentConfigsInsert, - TPkiAcmeEnrollmentConfigsUpdate -} from "@app/db/schemas/pki-acme-enrollment-configs"; export type TEstEnrollmentConfig = TPkiEstEnrollmentConfigs; export type TEstEnrollmentConfigInsert = TPkiEstEnrollmentConfigsInsert; diff --git a/frontend/src/hooks/api/secretApprovalRequest/types.ts b/frontend/src/hooks/api/secretApprovalRequest/types.ts index 5a381e871..5a25f1946 100644 --- a/frontend/src/hooks/api/secretApprovalRequest/types.ts +++ b/frontend/src/hooks/api/secretApprovalRequest/types.ts @@ -54,6 +54,7 @@ export type TSecretApprovalRequest = { lastName: string; username: string; isOrgMembershipActive: boolean; + createdAt: Date; }[]; project: string; environment: string; diff --git a/frontend/src/pages/cert-manager/PoliciesPage/components/CertificateProfilesTab/CertificateProfilesTab.tsx b/frontend/src/pages/cert-manager/PoliciesPage/components/CertificateProfilesTab/CertificateProfilesTab.tsx index 78517b49f..ab34abec8 100644 --- a/frontend/src/pages/cert-manager/PoliciesPage/components/CertificateProfilesTab/CertificateProfilesTab.tsx +++ b/frontend/src/pages/cert-manager/PoliciesPage/components/CertificateProfilesTab/CertificateProfilesTab.tsx @@ -1,6 +1,6 @@ +import { useState } from "react"; import { faPlus } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { useState } from "react"; import { createNotification } from "@app/components/notifications"; import { Button, DeleteActionModal } from "@app/components/v2"; diff --git a/frontend/src/pages/cert-manager/PoliciesPage/components/CertificateProfilesTab/CreateProfileModal.tsx b/frontend/src/pages/cert-manager/PoliciesPage/components/CertificateProfilesTab/CreateProfileModal.tsx index 40bc1f671..f53084a4e 100644 --- a/frontend/src/pages/cert-manager/PoliciesPage/components/CertificateProfilesTab/CreateProfileModal.tsx +++ b/frontend/src/pages/cert-manager/PoliciesPage/components/CertificateProfilesTab/CreateProfileModal.tsx @@ -1,8 +1,8 @@ +import { useEffect } from "react"; +import { Controller, useForm } from "react-hook-form"; import { faQuestionCircle } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { zodResolver } from "@hookform/resolvers/zod"; -import { useEffect } from "react"; -import { Controller, useForm } from "react-hook-form"; import { z } from "zod"; import { createNotification } from "@app/components/notifications"; diff --git a/frontend/src/pages/cert-manager/PoliciesPage/components/CertificateProfilesTab/ProfileRow.tsx b/frontend/src/pages/cert-manager/PoliciesPage/components/CertificateProfilesTab/ProfileRow.tsx index 1e6f259e1..009ebe1a4 100644 --- a/frontend/src/pages/cert-manager/PoliciesPage/components/CertificateProfilesTab/ProfileRow.tsx +++ b/frontend/src/pages/cert-manager/PoliciesPage/components/CertificateProfilesTab/ProfileRow.tsx @@ -1,3 +1,4 @@ +import { useCallback } from "react"; import { faCheck, faCircleInfo, @@ -9,7 +10,6 @@ import { faTrash } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { useCallback } from "react"; import { createNotification } from "@app/components/notifications"; import { diff --git a/frontend/src/pages/cert-manager/PoliciesPage/components/CertificateProfilesTab/RevealAcmeEabSecretModal.tsx b/frontend/src/pages/cert-manager/PoliciesPage/components/CertificateProfilesTab/RevealAcmeEabSecretModal.tsx index 628e4106b..970918cc0 100644 --- a/frontend/src/pages/cert-manager/PoliciesPage/components/CertificateProfilesTab/RevealAcmeEabSecretModal.tsx +++ b/frontend/src/pages/cert-manager/PoliciesPage/components/CertificateProfilesTab/RevealAcmeEabSecretModal.tsx @@ -1,3 +1,6 @@ +import { faCheck, faCopy } from "@fortawesome/free-solid-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; + import { Alert, AlertDescription, @@ -11,8 +14,6 @@ import { import { useToggle } from "@app/hooks"; import { TCertificateProfileWithDetails } from "@app/hooks/api/certificateProfiles"; import { useRevealAcmeEabSecret } from "@app/hooks/api/certificateProfiles/queries"; -import { faCheck, faCopy } from "@fortawesome/free-solid-svg-icons"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; const RESET_COPIED_DELAY = 1 * 1000; diff --git a/frontend/src/pages/secret-manager/SecretApprovalsPage/components/SecretApprovalRequest/components/SecretApprovalRequestChanges.tsx b/frontend/src/pages/secret-manager/SecretApprovalsPage/components/SecretApprovalRequest/components/SecretApprovalRequestChanges.tsx index bd4a04fa3..455cbd3bf 100644 --- a/frontend/src/pages/secret-manager/SecretApprovalsPage/components/SecretApprovalRequest/components/SecretApprovalRequestChanges.tsx +++ b/frontend/src/pages/secret-manager/SecretApprovalsPage/components/SecretApprovalRequest/components/SecretApprovalRequestChanges.tsx @@ -160,14 +160,18 @@ export const SecretApprovalRequestChanges = ({ approvalRequestId, onGoBack }: Pr secretApprovalRequestDetails.policy.bypassers.some(({ userId }) => userId === userSession.id); const reviewedUsers = secretApprovalRequestDetails?.reviewers?.reduce< - Record + Record< + string, + { status: ApprovalStatus; comment: string; isOrgMembershipActive: boolean; createdAt: Date } + > >( (prev, curr) => ({ ...prev, [curr.userId]: { status: curr.status, comment: curr.comment, - isOrgMembershipActive: curr.isOrgMembershipActive + isOrgMembershipActive: curr.isOrgMembershipActive, + createdAt: curr.createdAt } }), {} @@ -488,7 +492,7 @@ export const SecretApprovalRequestChanges = ({ approvalRequestId, onGoBack }: Pr {" "} the request on{" "} {format( - new Date(secretApprovalRequestDetails.createdAt), + new Date(reviewer ? reviewer.createdAt : new Date()), "MM/dd/yyyy h:mm:ss aa" )} .