diff --git a/backend/src/db/migrations/20251106172316_delete-pki-templates-on-project-removal.ts b/backend/src/db/migrations/20251106172316_delete-pki-templates-on-project-removal.ts new file mode 100644 index 000000000..4d98f8af4 --- /dev/null +++ b/backend/src/db/migrations/20251106172316_delete-pki-templates-on-project-removal.ts @@ -0,0 +1,21 @@ +import { Knex } from "knex"; + +import { TableName } from "../schemas"; + +export async function up(knex: Knex): Promise { + if (await knex.schema.hasTable(TableName.PkiCertificateTemplateV2)) { + await knex.schema.alterTable(TableName.PkiCertificateTemplateV2, (t) => { + t.dropForeign(["projectId"]); + t.foreign("projectId").references("id").inTable(TableName.Project).onDelete("CASCADE"); + }); + } +} + +export async function down(knex: Knex): Promise { + if (await knex.schema.hasTable(TableName.PkiCertificateTemplateV2)) { + await knex.schema.alterTable(TableName.PkiCertificateTemplateV2, (t) => { + t.dropForeign(["projectId"]); + t.foreign("projectId").references("id").inTable(TableName.Project); + }); + } +} diff --git a/backend/src/server/routes/v1/app-connection-routers/chef-connection-router.ts b/backend/src/ee/routes/v1/app-connection-routers/chef-connection-router.ts similarity index 92% rename from backend/src/server/routes/v1/app-connection-routers/chef-connection-router.ts rename to backend/src/ee/routes/v1/app-connection-routers/chef-connection-router.ts index 6bfd83391..2855d8b37 100644 --- a/backend/src/server/routes/v1/app-connection-routers/chef-connection-router.ts +++ b/backend/src/ee/routes/v1/app-connection-routers/chef-connection-router.ts @@ -1,17 +1,16 @@ import z from "zod"; -import { readLimit } from "@app/server/config/rateLimiter"; -import { verifyAuth } from "@app/server/plugins/auth/verify-auth"; -import { AppConnection } from "@app/services/app-connection/app-connection-enums"; import { CreateChefConnectionSchema, SanitizedChefConnectionSchema, UpdateChefConnectionSchema -} from "@app/services/app-connection/chef"; +} from "@app/ee/services/app-connections/chef"; +import { readLimit } from "@app/server/config/rateLimiter"; +import { verifyAuth } from "@app/server/plugins/auth/verify-auth"; +import { registerAppConnectionEndpoints } from "@app/server/routes/v1/app-connection-routers/app-connection-endpoints"; +import { AppConnection } from "@app/services/app-connection/app-connection-enums"; import { AuthMode } from "@app/services/auth/auth-type"; -import { registerAppConnectionEndpoints } from "./app-connection-endpoints"; - export const registerChefConnectionRouter = async (server: FastifyZodProvider) => { registerAppConnectionEndpoints({ app: AppConnection.Chef, diff --git a/backend/src/ee/routes/v1/pam-account-routers/pam-account-router.ts b/backend/src/ee/routes/v1/pam-account-routers/pam-account-router.ts index d2e0183ff..286e0896f 100644 --- a/backend/src/ee/routes/v1/pam-account-routers/pam-account-router.ts +++ b/backend/src/ee/routes/v1/pam-account-routers/pam-account-router.ts @@ -92,7 +92,8 @@ export const registerPamAccountRouter = async (server: FastifyZodProvider) => { gatewayClientCertificate: z.string(), gatewayClientPrivateKey: z.string(), gatewayServerCertificateChain: z.string(), - relayHost: z.string() + relayHost: z.string(), + metadata: z.record(z.string(), z.string()).optional() }) } }, diff --git a/backend/src/ee/routes/v1/pit-router.ts b/backend/src/ee/routes/v1/pit-router.ts index 14a82bce4..26909d294 100644 --- a/backend/src/ee/routes/v1/pit-router.ts +++ b/backend/src/ee/routes/v1/pit-router.ts @@ -468,7 +468,10 @@ export const registerPITRouter = async (server: FastifyZodProvider) => { .transform((val) => (val.at(-1) === "\n" ? `${val.trim()}\n` : val.trim())) .optional(), secretComment: z.string().trim().optional().default(""), - skipMultilineEncoding: z.boolean().optional(), + skipMultilineEncoding: z + .boolean() + .nullish() + .transform((val) => (val === null ? false : val)), metadata: z.record(z.string()).optional(), secretMetadata: ResourceMetadataSchema.optional(), tagIds: z.string().array().optional() diff --git a/backend/src/server/routes/v1/secret-sync-routers/chef-sync-router.ts b/backend/src/ee/routes/v1/secret-sync-routers/chef-sync-router.ts similarity index 72% rename from backend/src/server/routes/v1/secret-sync-routers/chef-sync-router.ts rename to backend/src/ee/routes/v1/secret-sync-routers/chef-sync-router.ts index 6972a9b70..3bdd5bce6 100644 --- a/backend/src/server/routes/v1/secret-sync-routers/chef-sync-router.ts +++ b/backend/src/ee/routes/v1/secret-sync-routers/chef-sync-router.ts @@ -1,8 +1,7 @@ -import { ChefSyncSchema, CreateChefSyncSchema, UpdateChefSyncSchema } from "@app/services/secret-sync/chef"; +import { ChefSyncSchema, CreateChefSyncSchema, UpdateChefSyncSchema } from "@app/ee/services/secret-sync/chef"; +import { registerSyncSecretsEndpoints } from "@app/server/routes/v1/secret-sync-routers/secret-sync-endpoints"; import { SecretSync } from "@app/services/secret-sync/secret-sync-enums"; -import { registerSyncSecretsEndpoints } from "./secret-sync-endpoints"; - export const registerChefSyncRouter = async (server: FastifyZodProvider) => registerSyncSecretsEndpoints({ destination: SecretSync.Chef, diff --git a/backend/src/services/app-connection/chef/chef-connection-enums.ts b/backend/src/ee/services/app-connections/chef/chef-connection-enums.ts similarity index 100% rename from backend/src/services/app-connection/chef/chef-connection-enums.ts rename to backend/src/ee/services/app-connections/chef/chef-connection-enums.ts diff --git a/backend/src/services/app-connection/chef/chef-connection-fns.ts b/backend/src/ee/services/app-connections/chef/chef-connection-fns.ts similarity index 99% rename from backend/src/services/app-connection/chef/chef-connection-fns.ts rename to backend/src/ee/services/app-connections/chef/chef-connection-fns.ts index 1b35628bc..6cef8373f 100644 --- a/backend/src/services/app-connection/chef/chef-connection-fns.ts +++ b/backend/src/ee/services/app-connections/chef/chef-connection-fns.ts @@ -5,10 +5,10 @@ import { request } from "@app/lib/config/request"; import { BadRequestError } from "@app/lib/errors"; import { removeTrailingSlash } from "@app/lib/fn"; import { blockLocalAndPrivateIpAddresses } from "@app/lib/validator"; +import { AppConnection } from "@app/services/app-connection/app-connection-enums"; import { IntegrationUrls } from "@app/services/integration-auth/integration-list"; import { TChefDataBagItemContent } from "../../secret-sync/chef/chef-sync-types"; -import { AppConnection } from "../app-connection-enums"; import { ChefConnectionMethod } from "./chef-connection-enums"; import { TChefConnection, diff --git a/backend/src/services/app-connection/chef/chef-connection-schemas.ts b/backend/src/ee/services/app-connections/chef/chef-connection-schemas.ts similarity index 100% rename from backend/src/services/app-connection/chef/chef-connection-schemas.ts rename to backend/src/ee/services/app-connections/chef/chef-connection-schemas.ts diff --git a/backend/src/services/app-connection/chef/chef-connection-service.ts b/backend/src/ee/services/app-connections/chef/chef-connection-service.ts similarity index 55% rename from backend/src/services/app-connection/chef/chef-connection-service.ts rename to backend/src/ee/services/app-connections/chef/chef-connection-service.ts index c989e7eaf..242b1fbf9 100644 --- a/backend/src/services/app-connection/chef/chef-connection-service.ts +++ b/backend/src/ee/services/app-connections/chef/chef-connection-service.ts @@ -1,7 +1,8 @@ -import { ForbiddenRequestError } from "@app/lib/errors"; +import { BadRequestError, ForbiddenRequestError } from "@app/lib/errors"; import { OrgServiceActor } from "@app/lib/types"; -import { AppConnection } from "../app-connection-enums"; +import { AppConnection } from "../../../../services/app-connection/app-connection-enums"; +import { TLicenseServiceFactory } from "../../license/license-service"; import { listChefDataBagItems, listChefDataBags } from "./chef-connection-fns"; import { TChefConnection } from "./chef-connection-types"; @@ -11,8 +12,23 @@ type TGetAppConnectionFunc = ( actor: OrgServiceActor ) => Promise; -export const chefConnectionService = (getAppConnection: TGetAppConnectionFunc) => { +// Enterprise check +export const checkPlan = async (licenseService: Pick, orgId: string) => { + const plan = await licenseService.getPlan(orgId); + if (!plan.enterpriseAppConnections) + throw new BadRequestError({ + message: + "Failed to use app connection due to plan restriction. Upgrade plan to access enterprise app connections." + }); +}; + +export const chefConnectionService = ( + getAppConnection: TGetAppConnectionFunc, + licenseService: Pick +) => { const listDataBags = async (appConnectionId: string, actor: OrgServiceActor) => { + await checkPlan(licenseService, actor.orgId); + const appConnection = await getAppConnection(AppConnection.Chef, appConnectionId, actor); if (!appConnection) { @@ -23,6 +39,8 @@ export const chefConnectionService = (getAppConnection: TGetAppConnectionFunc) = }; const listDataBagItems = async (appConnectionId: string, dataBagName: string, actor: OrgServiceActor) => { + await checkPlan(licenseService, actor.orgId); + const appConnection = await getAppConnection(AppConnection.Chef, appConnectionId, actor); if (!appConnection) { diff --git a/backend/src/services/app-connection/chef/chef-connection-types.ts b/backend/src/ee/services/app-connections/chef/chef-connection-types.ts similarity index 87% rename from backend/src/services/app-connection/chef/chef-connection-types.ts rename to backend/src/ee/services/app-connections/chef/chef-connection-types.ts index a2da80d3d..5673614e9 100644 --- a/backend/src/services/app-connection/chef/chef-connection-types.ts +++ b/backend/src/ee/services/app-connections/chef/chef-connection-types.ts @@ -1,9 +1,9 @@ import z from "zod"; +import { TChefDataBagItemContent } from "@app/ee/services/secret-sync/chef"; import { DiscriminativePick } from "@app/lib/types"; -import { TChefDataBagItemContent } from "@app/services/secret-sync/chef"; -import { AppConnection } from "../app-connection-enums"; +import { AppConnection } from "../../../../services/app-connection/app-connection-enums"; import { ChefConnectionSchema, CreateChefConnectionSchema, diff --git a/backend/src/services/app-connection/chef/index.ts b/backend/src/ee/services/app-connections/chef/index.ts similarity index 100% rename from backend/src/services/app-connection/chef/index.ts rename to backend/src/ee/services/app-connections/chef/index.ts diff --git a/backend/src/ee/services/gateway-v2/gateway-v2-service.ts b/backend/src/ee/services/gateway-v2/gateway-v2-service.ts index eaec31e50..22daa1cd1 100644 --- a/backend/src/ee/services/gateway-v2/gateway-v2-service.ts +++ b/backend/src/ee/services/gateway-v2/gateway-v2-service.ts @@ -3,7 +3,7 @@ import net from "node:net"; import { ForbiddenError } from "@casl/ability"; import * as x509 from "@peculiar/x509"; -import { OrganizationActionScope, OrgMembershipRole, TRelays } from "@app/db/schemas"; +import { OrganizationActionScope, OrgMembershipRole, OrgMembershipStatus, TRelays } from "@app/db/schemas"; import { PgSqlLock } from "@app/keystore/keystore"; import { crypto } from "@app/lib/crypto"; import { DatabaseErrorCode } from "@app/lib/error-codes"; @@ -909,7 +909,9 @@ export const gatewayV2ServiceFactory = ({ for await (const [orgId, gateways] of Object.entries(gatewaysByOrg)) { try { - const admins = await orgDAL.findOrgMembersByRole(orgId, OrgMembershipRole.Admin); + const admins = (await orgDAL.findOrgMembersByRole(orgId, OrgMembershipRole.Admin)).filter( + (admin) => admin.status !== OrgMembershipStatus.Invited + ); if (admins.length === 0) { logger.warn({ orgId }, "Organization has no admins to notify about unhealthy gateway."); // eslint-disable-next-line no-continue diff --git a/backend/src/ee/services/pam-account/pam-account-service.ts b/backend/src/ee/services/pam-account/pam-account-service.ts index 00b84943f..2f66d28d7 100644 --- a/backend/src/ee/services/pam-account/pam-account-service.ts +++ b/backend/src/ee/services/pam-account/pam-account-service.ts @@ -480,6 +480,36 @@ export const pamAccountServiceFactory = ({ throw new NotFoundError({ message: `Gateway connection details for gateway '${gatewayId}' not found.` }); } + let metadata; + + switch (resourceType) { + case PamResource.Postgres: + case PamResource.MySQL: + { + const connectionCredentials = await decryptResourceConnectionDetails({ + encryptedConnectionDetails: resource.encryptedConnectionDetails, + kmsService, + projectId: account.projectId + }); + + const credentials = await decryptAccountCredentials({ + encryptedCredentials: account.encryptedCredentials, + kmsService, + projectId: account.projectId + }); + + metadata = { + username: credentials.username, + database: connectionCredentials.database, + accountName: account.name, + accountPath + }; + } + break; + default: + break; + } + return { sessionId: session.id, resourceType, @@ -491,7 +521,8 @@ export const pamAccountServiceFactory = ({ gatewayServerCertificateChain: gatewayConnectionDetails.gateway.serverCertificateChain, relayHost: gatewayConnectionDetails.relayHost, projectId: account.projectId, - account + account, + metadata }; }; diff --git a/backend/src/ee/services/pam-resource/shared/sql/sql-resource-factory.ts b/backend/src/ee/services/pam-resource/shared/sql/sql-resource-factory.ts index 99ce2d25f..413990c5d 100644 --- a/backend/src/ee/services/pam-resource/shared/sql/sql-resource-factory.ts +++ b/backend/src/ee/services/pam-resource/shared/sql/sql-resource-factory.ts @@ -1,6 +1,5 @@ import knex from "knex"; import mysql, { Connection } from "mysql2/promise"; -import * as pg from "pg"; import tls, { PeerCertificate } from "tls"; import { verifyHostInputValidity } from "@app/ee/services/dynamic-secret/dynamic-secret-fns"; @@ -97,7 +96,7 @@ const makeSqlConnection = ( try { await client.raw(SIMPLE_QUERY); } catch (error) { - if (error instanceof pg.DatabaseError) { + if (error instanceof Error) { // Hacky way to know if we successfully hit the database. // TODO: potentially two approaches to solve the problem. // 1. change the work flow, add account first then resource diff --git a/backend/src/ee/services/permission/permission-dal.ts b/backend/src/ee/services/permission/permission-dal.ts index 95480a54a..88b52be22 100644 --- a/backend/src/ee/services/permission/permission-dal.ts +++ b/backend/src/ee/services/permission/permission-dal.ts @@ -201,11 +201,11 @@ export const permissionDALFactory = (db: TDbClient): TPermissionDALFactory => { .leftJoin(TableName.IdentityMetadata, (queryBuilder) => { if (actorType === ActorType.USER) { void queryBuilder - .on(`${TableName.Membership}.actorUserId`, `${TableName.IdentityMetadata}.userId`) + .on(`${TableName.IdentityMetadata}.userId`, db.raw("?", [actorId])) .andOn(`${TableName.Membership}.scopeOrgId`, `${TableName.IdentityMetadata}.orgId`); } else if (actorType === ActorType.IDENTITY) { void queryBuilder - .on(`${TableName.Membership}.actorIdentityId`, `${TableName.IdentityMetadata}.identityId`) + .on(`${TableName.IdentityMetadata}.identityId`, db.raw("?", [actorId])) .andOn(`${TableName.Membership}.scopeOrgId`, `${TableName.IdentityMetadata}.orgId`); } }) @@ -488,7 +488,7 @@ export const permissionDALFactory = (db: TDbClient): TPermissionDALFactory => { }) .leftJoin(TableName.IdentityMetadata, (queryBuilder) => { void queryBuilder - .on(`${TableName.Membership}.actorUserId`, `${TableName.IdentityMetadata}.userId`) + .on(`${TableName.Users}.id`, `${TableName.IdentityMetadata}.userId`) .andOn(`${TableName.Membership}.scopeOrgId`, `${TableName.IdentityMetadata}.orgId`); }) .where(`${TableName.Membership}.scopeOrgId`, orgId) diff --git a/backend/src/ee/services/relay/relay-service.ts b/backend/src/ee/services/relay/relay-service.ts index 096011765..ae7758e67 100644 --- a/backend/src/ee/services/relay/relay-service.ts +++ b/backend/src/ee/services/relay/relay-service.ts @@ -3,7 +3,7 @@ import { isIP } from "node:net"; import { ForbiddenError } from "@casl/ability"; import * as x509 from "@peculiar/x509"; -import { OrganizationActionScope, OrgMembershipRole, TRelays } from "@app/db/schemas"; +import { OrganizationActionScope, OrgMembershipRole, OrgMembershipStatus, TRelays } from "@app/db/schemas"; import { PgSqlLock } from "@app/keystore/keystore"; import { crypto } from "@app/lib/crypto"; import { BadRequestError, ForbiddenRequestError, NotFoundError } from "@app/lib/errors"; @@ -996,7 +996,9 @@ export const relayServiceFactory = ({ ); if (existingRelay && (existingRelay.host !== host || existingRelay.name !== name)) { - return relayDAL.updateById(existingRelay.id, { host, name }, tx); + throw new BadRequestError({ + message: `Machine identity already has an existing relay with the name "${existingRelay.name}" and host "${existingRelay.host}". Delete the existing relay or use a different machine identity.` + }); } if (!existingRelay) { @@ -1248,7 +1250,9 @@ export const relayServiceFactory = ({ }); } } else { - const admins = await orgDAL.findOrgMembersByRole(orgId, OrgMembershipRole.Admin); + const admins = (await orgDAL.findOrgMembersByRole(orgId, OrgMembershipRole.Admin)).filter( + (admin) => admin.status !== OrgMembershipStatus.Invited + ); if (admins.length === 0) { // eslint-disable-next-line no-continue continue; 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 7597dcfd4..db300720f 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 @@ -670,6 +670,7 @@ export const secretApprovalRequestDALFactory = (db: TDbClient) => { .select( db.ref("projectId").withSchema(TableName.Environment), db.ref("slug").withSchema(TableName.Environment).as("environment"), + db.ref("name").withSchema(TableName.Environment).as("environmentName"), db.ref("id").withSchema(TableName.SecretApprovalRequestReviewer).as("reviewerId"), db.ref("reviewerUserId").withSchema(TableName.SecretApprovalRequestReviewer), db.ref("status").withSchema(TableName.SecretApprovalRequestReviewer).as("reviewerStatus"), @@ -699,30 +700,30 @@ export const secretApprovalRequestDALFactory = (db: TDbClient) => { ) .as("inner"); - const countQuery = (await (tx || db) - .select(db.raw("count(*) OVER() as total_count")) - .from(innerQuery.clone().distinctOn(`${TableName.SecretApprovalRequest}.id`))) as Array<{ - total_count: number; - }>; - const query = (tx || db).select("*").from(innerQuery).orderBy("createdAt", "desc") as typeof innerQuery; if (search) { void query.where((qb) => { void qb .whereRaw(`CONCAT_WS(' ', ??, ??) ilike ?`, [ - db.ref("firstName").withSchema("committerUser"), - db.ref("lastName").withSchema("committerUser"), + db.ref("committerUserFirstName"), + db.ref("committerUserLastName"), `%${search}%` ]) - .orWhereRaw(`?? ilike ?`, [db.ref("username").withSchema("committerUser"), `%${search}%`]) - .orWhereRaw(`?? ilike ?`, [db.ref("email").withSchema("committerUser"), `%${search}%`]) - .orWhereILike(`${TableName.Environment}.name`, `%${search}%`) - .orWhereILike(`${TableName.Environment}.slug`, `%${search}%`) - .orWhereILike(`${TableName.SecretApprovalPolicy}.secretPath`, `%${search}%`); + .orWhereRaw(`?? ilike ?`, [db.ref("committerUserUsername"), `%${search}%`]) + .orWhereRaw(`?? ilike ?`, [db.ref("committerUserEmail"), `%${search}%`]) + .orWhereILike(`environmentName`, `%${search}%`) + .orWhereILike(`environment`, `%${search}%`) + .orWhereILike(`policySecretPath`, `%${search}%`); }); } + const countQuery = (await (tx || db) + .select(db.raw("count(*) OVER() as total_count")) + .from(query.clone().as("outer"))) as Array<{ + total_count: number; + }>; + const rankOffset = offset + 1; const docs = await (tx || db) .with("w", query) diff --git a/backend/src/services/secret-sync/chef/chef-sync-constants.ts b/backend/src/ee/services/secret-sync/chef/chef-sync-constants.ts similarity index 89% rename from backend/src/services/secret-sync/chef/chef-sync-constants.ts rename to backend/src/ee/services/secret-sync/chef/chef-sync-constants.ts index 567b25bbe..8bbf0e12a 100644 --- a/backend/src/services/secret-sync/chef/chef-sync-constants.ts +++ b/backend/src/ee/services/secret-sync/chef/chef-sync-constants.ts @@ -6,5 +6,6 @@ export const CHEF_SYNC_LIST_OPTION: TSecretSyncListItem = { name: "Chef", destination: SecretSync.Chef, connection: AppConnection.Chef, - canImportSecrets: true + canImportSecrets: true, + enterprise: true }; diff --git a/backend/src/services/secret-sync/chef/chef-sync-fns.ts b/backend/src/ee/services/secret-sync/chef/chef-sync-fns.ts similarity index 99% rename from backend/src/services/secret-sync/chef/chef-sync-fns.ts rename to backend/src/ee/services/secret-sync/chef/chef-sync-fns.ts index 7f32b398a..65a4fca9b 100644 --- a/backend/src/services/secret-sync/chef/chef-sync-fns.ts +++ b/backend/src/ee/services/secret-sync/chef/chef-sync-fns.ts @@ -1,4 +1,4 @@ -import { getChefDataBagItem, updateChefDataBagItem } from "@app/services/app-connection/chef"; +import { getChefDataBagItem, updateChefDataBagItem } from "@app/ee/services/app-connections/chef"; import { matchesSchema } from "@app/services/secret-sync/secret-sync-fns"; import { TSecretMap } from "@app/services/secret-sync/secret-sync-types"; diff --git a/backend/src/services/secret-sync/chef/chef-sync-schemas.ts b/backend/src/ee/services/secret-sync/chef/chef-sync-schemas.ts similarity index 96% rename from backend/src/services/secret-sync/chef/chef-sync-schemas.ts rename to backend/src/ee/services/secret-sync/chef/chef-sync-schemas.ts index c2e09011e..9702f97d3 100644 --- a/backend/src/services/secret-sync/chef/chef-sync-schemas.ts +++ b/backend/src/ee/services/secret-sync/chef/chef-sync-schemas.ts @@ -42,5 +42,6 @@ export const ChefSyncListItemSchema = z.object({ name: z.literal("Chef"), connection: z.literal(AppConnection.Chef), destination: z.literal(SecretSync.Chef), - canImportSecrets: z.literal(true) + canImportSecrets: z.literal(true), + enterprise: z.boolean() }); diff --git a/backend/src/services/secret-sync/chef/chef-sync-types.ts b/backend/src/ee/services/secret-sync/chef/chef-sync-types.ts similarity index 92% rename from backend/src/services/secret-sync/chef/chef-sync-types.ts rename to backend/src/ee/services/secret-sync/chef/chef-sync-types.ts index 464e0372d..0f70e7e1a 100644 --- a/backend/src/services/secret-sync/chef/chef-sync-types.ts +++ b/backend/src/ee/services/secret-sync/chef/chef-sync-types.ts @@ -1,6 +1,6 @@ import z from "zod"; -import { TChefConnection } from "@app/services/app-connection/chef"; +import { TChefConnection } from "@app/ee/services/app-connections/chef"; import { ChefSyncListItemSchema, ChefSyncSchema, CreateChefSyncSchema } from "./chef-sync-schemas"; diff --git a/backend/src/services/secret-sync/chef/index.ts b/backend/src/ee/services/secret-sync/chef/index.ts similarity index 100% rename from backend/src/services/secret-sync/chef/index.ts rename to backend/src/ee/services/secret-sync/chef/index.ts diff --git a/backend/src/server/routes/sanitizedSchemas.ts b/backend/src/server/routes/sanitizedSchemas.ts index 47fbb0e07..17cfcb5ce 100644 --- a/backend/src/server/routes/sanitizedSchemas.ts +++ b/backend/src/server/routes/sanitizedSchemas.ts @@ -141,7 +141,8 @@ export const secretRawSchema = z.object({ actorId: z.string().nullable().optional(), actorType: z.string().nullable().optional(), name: z.string().nullable().optional(), - membershipId: z.string().nullable().optional() + membershipId: z.string().nullable().optional(), + groupId: z.string().nullable().optional() }) .optional() .nullable(), diff --git a/backend/src/server/routes/v1/app-connection-routers/app-connection-router.ts b/backend/src/server/routes/v1/app-connection-routers/app-connection-router.ts index 9a4d7f38b..5a3496750 100644 --- a/backend/src/server/routes/v1/app-connection-routers/app-connection-router.ts +++ b/backend/src/server/routes/v1/app-connection-routers/app-connection-router.ts @@ -1,6 +1,7 @@ import { z } from "zod"; import { ProjectType } from "@app/db/schemas"; +import { ChefConnectionListItemSchema, SanitizedChefConnectionSchema } from "@app/ee/services/app-connections/chef"; import { OCIConnectionListItemSchema, SanitizedOCIConnectionSchema } from "@app/ee/services/app-connections/oci"; import { OracleDBConnectionListItemSchema, @@ -48,7 +49,6 @@ import { ChecklyConnectionListItemSchema, SanitizedChecklyConnectionSchema } from "@app/services/app-connection/checkly"; -import { ChefConnectionListItemSchema, SanitizedChefConnectionSchema } from "@app/services/app-connection/chef"; import { CloudflareConnectionListItemSchema, SanitizedCloudflareConnectionSchema diff --git a/backend/src/server/routes/v1/app-connection-routers/index.ts b/backend/src/server/routes/v1/app-connection-routers/index.ts index 32e9efe4c..aa1d671b6 100644 --- a/backend/src/server/routes/v1/app-connection-routers/index.ts +++ b/backend/src/server/routes/v1/app-connection-routers/index.ts @@ -1,3 +1,4 @@ +import { registerChefConnectionRouter } from "@app/ee/routes/v1/app-connection-routers/chef-connection-router"; import { registerOCIConnectionRouter } from "@app/ee/routes/v1/app-connection-routers/oci-connection-router"; import { registerOracleDBConnectionRouter } from "@app/ee/routes/v1/app-connection-routers/oracledb-connection-router"; import { AppConnection } from "@app/services/app-connection/app-connection-enums"; @@ -13,7 +14,6 @@ import { registerAzureKeyVaultConnectionRouter } from "./azure-key-vault-connect import { registerBitbucketConnectionRouter } from "./bitbucket-connection-router"; import { registerCamundaConnectionRouter } from "./camunda-connection-router"; import { registerChecklyConnectionRouter } from "./checkly-connection-router"; -import { registerChefConnectionRouter } from "./chef-connection-router"; import { registerCloudflareConnectionRouter } from "./cloudflare-connection-router"; import { registerDatabricksConnectionRouter } from "./databricks-connection-router"; import { registerDigitalOceanConnectionRouter } from "./digital-ocean-connection-router"; diff --git a/backend/src/server/routes/v1/project-membership-router.ts b/backend/src/server/routes/v1/project-membership-router.ts index 57fdad031..dc76efa92 100644 --- a/backend/src/server/routes/v1/project-membership-router.ts +++ b/backend/src/server/routes/v1/project-membership-router.ts @@ -2,6 +2,7 @@ import { z } from "zod"; import { AccessScope, + OrgMembershipRole, ProjectMembershipRole, ProjectMembershipsSchema, ProjectUserMembershipRolesSchema, @@ -266,6 +267,19 @@ export const registerProjectMembershipRouter = async (server: FastifyZodProvider onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY, AuthMode.IDENTITY_ACCESS_TOKEN]), handler: async (req) => { const usernamesAndEmails = [...req.body.emails, ...req.body.usernames]; + + await server.services.membershipUser.createMembership({ + permission: req.permission, + scopeData: { + scope: AccessScope.Organization, + orgId: req.permission.orgId + }, + data: { + roles: [{ isTemporary: false, role: OrgMembershipRole.NoAccess }], + usernames: usernamesAndEmails + } + }); + const { memberships } = await server.services.membershipUser.createMembership({ permission: req.permission, scopeData: { diff --git a/backend/src/server/routes/v1/secret-sync-routers/index.ts b/backend/src/server/routes/v1/secret-sync-routers/index.ts index d305dc342..810e5b7fa 100644 --- a/backend/src/server/routes/v1/secret-sync-routers/index.ts +++ b/backend/src/server/routes/v1/secret-sync-routers/index.ts @@ -1,3 +1,4 @@ +import { registerChefSyncRouter } from "@app/ee/routes/v1/secret-sync-routers/chef-sync-router"; import { registerOCIVaultSyncRouter } from "@app/ee/routes/v1/secret-sync-routers/oci-vault-sync-router"; import { SecretSync } from "@app/services/secret-sync/secret-sync-enums"; @@ -10,7 +11,6 @@ import { registerAzureKeyVaultSyncRouter } from "./azure-key-vault-sync-router"; import { registerBitbucketSyncRouter } from "./bitbucket-sync-router"; import { registerCamundaSyncRouter } from "./camunda-sync-router"; import { registerChecklySyncRouter } from "./checkly-sync-router"; -import { registerChefSyncRouter } from "./chef-sync-router"; import { registerCloudflarePagesSyncRouter } from "./cloudflare-pages-sync-router"; import { registerCloudflareWorkersSyncRouter } from "./cloudflare-workers-sync-router"; import { registerDatabricksSyncRouter } from "./databricks-sync-router"; diff --git a/backend/src/server/routes/v1/secret-sync-routers/secret-sync-router.ts b/backend/src/server/routes/v1/secret-sync-routers/secret-sync-router.ts index 85adf12f1..61e4ab79d 100644 --- a/backend/src/server/routes/v1/secret-sync-routers/secret-sync-router.ts +++ b/backend/src/server/routes/v1/secret-sync-routers/secret-sync-router.ts @@ -1,6 +1,7 @@ import { z } from "zod"; import { EventType } from "@app/ee/services/audit-log/audit-log-types"; +import { ChefSyncListItemSchema, ChefSyncSchema } from "@app/ee/services/secret-sync/chef"; import { OCIVaultSyncListItemSchema, OCIVaultSyncSchema } from "@app/ee/services/secret-sync/oci-vault"; import { ApiDocsTags, SecretSyncs } from "@app/lib/api-docs"; import { readLimit } from "@app/server/config/rateLimiter"; @@ -24,7 +25,6 @@ import { AzureKeyVaultSyncListItemSchema, AzureKeyVaultSyncSchema } from "@app/s import { BitbucketSyncListItemSchema, BitbucketSyncSchema } from "@app/services/secret-sync/bitbucket"; import { CamundaSyncListItemSchema, CamundaSyncSchema } from "@app/services/secret-sync/camunda"; import { ChecklySyncListItemSchema, ChecklySyncSchema } from "@app/services/secret-sync/checkly/checkly-sync-schemas"; -import { ChefSyncListItemSchema, ChefSyncSchema } from "@app/services/secret-sync/chef"; import { CloudflarePagesSyncListItemSchema, CloudflarePagesSyncSchema diff --git a/backend/src/server/routes/v1/sso-router.ts b/backend/src/server/routes/v1/sso-router.ts index 32b09b337..63f673d3f 100644 --- a/backend/src/server/routes/v1/sso-router.ts +++ b/backend/src/server/routes/v1/sso-router.ts @@ -550,12 +550,14 @@ export const registerSsoRouter = async (server: FastifyZodProvider) => { providerAuthToken: req.body.providerAuthToken }); - void res.setCookie("jid", data.token.refresh, { - httpOnly: true, - path: "/", - sameSite: "strict", - secure: appCfg.HTTPS_ENABLED - }); + if ([AuthMethod.GOOGLE, AuthMethod.GITHUB, AuthMethod.GITLAB].includes(data.decodedProviderToken.authMethod)) { + void res.setCookie("jid", data.token.refresh, { + httpOnly: true, + path: "/", + sameSite: "strict", + secure: appCfg.HTTPS_ENABLED + }); + } addAuthOriginDomainCookie(res); diff --git a/backend/src/services/app-connection/app-connection-fns.ts b/backend/src/services/app-connection/app-connection-fns.ts index 3c511fd4d..863fa75f9 100644 --- a/backend/src/services/app-connection/app-connection-fns.ts +++ b/backend/src/services/app-connection/app-connection-fns.ts @@ -1,5 +1,10 @@ import { ProjectType } from "@app/db/schemas"; import { TAppConnections } from "@app/db/schemas/app-connections"; +import { + ChefConnectionMethod, + getChefConnectionListItem, + validateChefConnectionCredentials +} from "@app/ee/services/app-connections/chef"; import { getOCIConnectionListItem, OCIConnectionMethod, @@ -68,7 +73,6 @@ import { } from "./bitbucket"; import { CamundaConnectionMethod, getCamundaConnectionListItem, validateCamundaConnectionCredentials } from "./camunda"; import { ChecklyConnectionMethod, getChecklyConnectionListItem, validateChecklyConnectionCredentials } from "./checkly"; -import { ChefConnectionMethod, getChefConnectionListItem, validateChefConnectionCredentials } from "./chef"; import { CloudflareConnectionMethod } from "./cloudflare/cloudflare-connection-enum"; import { getCloudflareConnectionListItem, diff --git a/backend/src/services/app-connection/app-connection-maps.ts b/backend/src/services/app-connection/app-connection-maps.ts index 08ca0c681..5b8cc3fc1 100644 --- a/backend/src/services/app-connection/app-connection-maps.ts +++ b/backend/src/services/app-connection/app-connection-maps.ts @@ -86,6 +86,6 @@ export const APP_CONNECTION_PLAN_MAP: Record; try { diff --git a/backend/src/services/identity-token-auth/identity-token-auth-service.ts b/backend/src/services/identity-token-auth/identity-token-auth-service.ts index 2d3e11cd8..e6969da61 100644 --- a/backend/src/services/identity-token-auth/identity-token-auth-service.ts +++ b/backend/src/services/identity-token-auth/identity-token-auth-service.ts @@ -244,8 +244,8 @@ export const identityTokenAuthServiceFactory = ({ } if (!identityMembershipOrg.identity.authMethods.includes(IdentityAuthMethod.TOKEN_AUTH)) { - throw new BadRequestError({ - message: "The identity does not have Token Auth attached" + throw new NotFoundError({ + message: "Token Auth configuration not found for identity" }); } diff --git a/backend/src/services/secret-folder/secret-folder-dal.ts b/backend/src/services/secret-folder/secret-folder-dal.ts index 7dfeaddcf..f2befbe1a 100644 --- a/backend/src/services/secret-folder/secret-folder-dal.ts +++ b/backend/src/services/secret-folder/secret-folder-dal.ts @@ -419,13 +419,14 @@ export const secretFolderDALFactory = (db: TDbClient) => { .select( selectAllTableCols(TableName.SecretFolder), db.raw( - `DENSE_RANK() OVER (ORDER BY ${TableName.SecretFolder}."name" ${ - orderDirection ?? OrderByDirection.ASC - }) as rank` + `DENSE_RANK() OVER (ORDER BY ${TableName.SecretFolder}."name" COLLATE "en-x-icu" ${orderDirection === OrderByDirection.ASC ? "ASC" : "DESC"}) as rank` ), db.ref("slug").withSchema(TableName.Environment).as("environment") ) - .orderBy(`${TableName.SecretFolder}.${orderBy}`, orderDirection); + .orderByRaw( + `${TableName.SecretFolder}.?? COLLATE "en-x-icu" ${orderDirection === OrderByDirection.ASC ? "ASC" : "DESC"}`, + [orderBy] + ); if (limit) { const rankOffset = offset + 1; // ranks start from 1 @@ -434,7 +435,10 @@ export const secretFolderDALFactory = (db: TDbClient) => { .select("*") .from[number]>("w") .where("w.rank", ">=", rankOffset) - .andWhere("w.rank", "<", rankOffset + limit); + .andWhere("w.rank", "<", rankOffset + limit) + .orderByRaw(`"w".?? COLLATE "en-x-icu" ${orderDirection === OrderByDirection.ASC ? "ASC" : "DESC"}`, [ + orderBy + ]); } const folders = await query; @@ -445,7 +449,10 @@ export const secretFolderDALFactory = (db: TDbClient) => { } }; - const findByEnvsDeep = async ({ parentIds }: TFindFoldersDeepByParentIdsDTO, tx?: Knex) => { + const findByEnvsDeep = async ( + { parentIds, orderBy = SecretsOrderBy.Name, orderDirection = OrderByDirection.ASC }: TFindFoldersDeepByParentIdsDTO, + tx?: Knex + ) => { try { const folders = await (tx || db.replicaNode()) .withRecursive("parents", (qb) => @@ -480,7 +487,9 @@ export const secretFolderDALFactory = (db: TDbClient) => { .select<(TSecretFolders & { path: string; depth: number; environment: string })[]>("*") .from("parents") .orderBy("depth") - .orderBy(`name`); + .orderByRaw(`"parents".?? COLLATE "en-x-icu" ${orderDirection === OrderByDirection.ASC ? "ASC" : "DESC"}`, [ + orderBy + ]); return folders; } catch (error) { diff --git a/backend/src/services/secret-folder/secret-folder-service.ts b/backend/src/services/secret-folder/secret-folder-service.ts index c216ea3a8..033efdb14 100644 --- a/backend/src/services/secret-folder/secret-folder-service.ts +++ b/backend/src/services/secret-folder/secret-folder-service.ts @@ -14,6 +14,7 @@ import { PgSqlLock } from "@app/keystore/keystore"; import { BadRequestError, NotFoundError } from "@app/lib/errors"; import { OrderByDirection, OrgServiceActor } from "@app/lib/types"; import { ActorType } from "@app/services/auth/auth-type"; +import { SecretsOrderBy } from "@app/services/secret/secret-types"; import { buildFolderPath } from "@app/services/secret-folder/secret-folder-fns"; import { @@ -781,7 +782,11 @@ export const secretFolderServiceFactory = ({ if (!parentFolder) return []; if (recursive) { - const recursiveFolders = await folderDAL.findByEnvsDeep({ parentIds: [parentFolder.id] }); + const recursiveFolders = await folderDAL.findByEnvsDeep({ + parentIds: [parentFolder.id], + orderBy: orderBy || SecretsOrderBy.Name, + orderDirection: orderDirection || OrderByDirection.ASC + }); // remove the parent folder return recursiveFolders .filter((folder) => { @@ -800,19 +805,15 @@ export const secretFolderServiceFactory = ({ })); } - const folders = await folderDAL.find( - { - envId: env.id, - parentId: parentFolder.id, - isReserved: false, - $search: search ? { name: `%${search}%` } : undefined - }, - { - sort: orderBy ? [[orderBy, orderDirection ?? OrderByDirection.ASC]] : undefined, - limit, - offset - } - ); + const folders = await folderDAL.findByMultiEnv({ + environmentIds: [env.id], + parentIds: [parentFolder.id], + search, + orderBy: orderBy || SecretsOrderBy.Name, + orderDirection: orderDirection || OrderByDirection.ASC, + limit, + offset + }); if (lastSecretModified) { return folders.filter((el) => el.lastSecretModified ? el.lastSecretModified >= new Date(lastSecretModified) : false diff --git a/backend/src/services/secret-folder/secret-folder-types.ts b/backend/src/services/secret-folder/secret-folder-types.ts index da8be52a0..d220c29d2 100644 --- a/backend/src/services/secret-folder/secret-folder-types.ts +++ b/backend/src/services/secret-folder/secret-folder-types.ts @@ -64,6 +64,8 @@ export type TGetFoldersDeepByEnvsDTO = { export type TFindFoldersDeepByParentIdsDTO = { parentIds: string[]; + orderBy?: SecretsOrderBy; + orderDirection?: OrderByDirection; }; export type TCreateManyFoldersDTO = { diff --git a/backend/src/services/secret-sync/secret-sync-fns.ts b/backend/src/services/secret-sync/secret-sync-fns.ts index 77845535f..6ee9b91d3 100644 --- a/backend/src/services/secret-sync/secret-sync-fns.ts +++ b/backend/src/services/secret-sync/secret-sync-fns.ts @@ -4,6 +4,7 @@ import handlebars from "handlebars"; import { TGatewayServiceFactory } from "@app/ee/services/gateway/gateway-service"; import { TGatewayV2ServiceFactory } from "@app/ee/services/gateway-v2/gateway-v2-service"; import { TLicenseServiceFactory } from "@app/ee/services/license/license-service"; +import { CHEF_SYNC_LIST_OPTION, ChefSyncFns } from "@app/ee/services/secret-sync/chef"; import { OCI_VAULT_SYNC_LIST_OPTION, OCIVaultSyncFns } from "@app/ee/services/secret-sync/oci-vault"; import { BadRequestError } from "@app/lib/errors"; import { @@ -34,7 +35,6 @@ import { BITBUCKET_SYNC_LIST_OPTION, BitbucketSyncFns } from "./bitbucket"; import { CAMUNDA_SYNC_LIST_OPTION, camundaSyncFactory } from "./camunda"; import { CHECKLY_SYNC_LIST_OPTION } from "./checkly/checkly-sync-constants"; import { ChecklySyncFns } from "./checkly/checkly-sync-fns"; -import { CHEF_SYNC_LIST_OPTION, ChefSyncFns } from "./chef"; import { CLOUDFLARE_PAGES_SYNC_LIST_OPTION } from "./cloudflare-pages/cloudflare-pages-constants"; import { CloudflarePagesSyncFns } from "./cloudflare-pages/cloudflare-pages-fns"; import { CLOUDFLARE_WORKERS_SYNC_LIST_OPTION, CloudflareWorkersSyncFns } from "./cloudflare-workers"; diff --git a/backend/src/services/secret-sync/secret-sync-maps.ts b/backend/src/services/secret-sync/secret-sync-maps.ts index 86cb189c3..529634a6d 100644 --- a/backend/src/services/secret-sync/secret-sync-maps.ts +++ b/backend/src/services/secret-sync/secret-sync-maps.ts @@ -107,7 +107,7 @@ export const SECRET_SYNC_PLAN_MAP: Record = { [SecretSync.Northflank]: SecretSyncPlanType.Regular, [SecretSync.Bitbucket]: SecretSyncPlanType.Regular, [SecretSync.LaravelForge]: SecretSyncPlanType.Regular, - [SecretSync.Chef]: SecretSyncPlanType.Regular + [SecretSync.Chef]: SecretSyncPlanType.Enterprise }; export const SECRET_SYNC_SKIP_FIELDS_MAP: Record = { diff --git a/backend/src/services/secret-sync/secret-sync-types.ts b/backend/src/services/secret-sync/secret-sync-types.ts index d6ef0b3fc..f1a87a9d2 100644 --- a/backend/src/services/secret-sync/secret-sync-types.ts +++ b/backend/src/services/secret-sync/secret-sync-types.ts @@ -1,6 +1,12 @@ import { Job } from "bullmq"; import { AuditLogInfo } from "@app/ee/services/audit-log/audit-log-types"; +import { + TChefSync, + TChefSyncInput, + TChefSyncListItem, + TChefSyncWithCredentials +} from "@app/ee/services/secret-sync/chef"; import { TOCIVaultSync, TOCIVaultSyncInput, @@ -21,7 +27,6 @@ import { TCamundaSyncListItem, TCamundaSyncWithCredentials } from "@app/services/secret-sync/camunda"; -import { TChefSync, TChefSyncInput, TChefSyncListItem, TChefSyncWithCredentials } from "@app/services/secret-sync/chef"; import { TDatabricksSync, TDatabricksSyncInput, diff --git a/backend/src/services/secret-v2-bridge/secret-v2-bridge-fns.ts b/backend/src/services/secret-v2-bridge/secret-v2-bridge-fns.ts index 6b284ddee..01a7f6210 100644 --- a/backend/src/services/secret-v2-bridge/secret-v2-bridge-fns.ts +++ b/backend/src/services/secret-v2-bridge/secret-v2-bridge-fns.ts @@ -793,6 +793,7 @@ export const reshapeBridgeSecret = ( userActorId?: string | null; identityActorId?: string | null; membershipId?: string | null; + groupId?: string | null; actorType?: string | null; tags?: { id: string; @@ -823,7 +824,8 @@ export const reshapeBridgeSecret = ( actorType: secret.actorType, actorId: secret.userActorId || secret.identityActorId, name: secret.identityActorName || secret.userActorName, - membershipId: secret.membershipId + membershipId: secret.membershipId, + groupId: secret.groupId } : undefined, tags: secret.tags, diff --git a/backend/src/services/secret-v2-bridge/secret-version-dal.ts b/backend/src/services/secret-v2-bridge/secret-version-dal.ts index 7d25dac86..a7f0eb565 100644 --- a/backend/src/services/secret-v2-bridge/secret-version-dal.ts +++ b/backend/src/services/secret-v2-bridge/secret-version-dal.ts @@ -182,7 +182,6 @@ export const secretVersionV2BridgeDALFactory = (db: TDbClient) => { const findVersionsBySecretIdWithActors = async ({ secretId, - projectId, secretVersions, findOpt = {}, tx @@ -196,13 +195,22 @@ export const secretVersionV2BridgeDALFactory = (db: TDbClient) => { try { const { offset, limit, sort = [["createdAt", "desc"]] } = findOpt; const query = (tx || db.replicaNode())(TableName.SecretVersionV2) + .leftJoin(TableName.SecretFolder, `${TableName.SecretFolder}.id`, `${TableName.SecretVersionV2}.folderId`) + .leftJoin(TableName.Environment, `${TableName.Environment}.id`, `${TableName.SecretFolder}.envId`) .leftJoin(TableName.Users, `${TableName.Users}.id`, `${TableName.SecretVersionV2}.userActorId`) + .leftJoin(TableName.Identity, `${TableName.Identity}.id`, `${TableName.SecretVersionV2}.identityActorId`) + .leftJoin(TableName.UserGroupMembership, `${TableName.UserGroupMembership}.userId`, `${TableName.Users}.id`) .leftJoin(TableName.Membership, (qb) => { void qb - .on(`${TableName.Membership}.actorUserId`, `${TableName.SecretVersionV2}.userActorId`) - .andOn(`${TableName.Membership}.scope`, db.raw("?", [AccessScope.Project])); + .on(`${TableName.Membership}.scope`, db.raw("?", [AccessScope.Project])) + .andOn(`${TableName.Membership}.scopeProjectId`, `${TableName.Environment}.projectId`) + .andOn((sqb) => { + void sqb + .on(`${TableName.Membership}.actorUserId`, `${TableName.SecretVersionV2}.userActorId`) + .orOn(`${TableName.Membership}.actorIdentityId`, `${TableName.SecretVersionV2}.identityActorId`) + .orOn(`${TableName.Membership}.actorGroupId`, `${TableName.UserGroupMembership}.groupId`); + }); }) - .leftJoin(TableName.Identity, `${TableName.Identity}.id`, `${TableName.SecretVersionV2}.identityActorId`) .leftJoin(TableName.SecretV2, `${TableName.SecretVersionV2}.secretId`, `${TableName.SecretV2}.id`) .leftJoin( TableName.SecretVersionV2Tag, @@ -216,12 +224,6 @@ export const secretVersionV2BridgeDALFactory = (db: TDbClient) => { ) .where((qb) => { void qb.where(`${TableName.SecretVersionV2}.secretId`, secretId); - void qb.where(`${TableName.Membership}.scopeProjectId`, projectId); - if (secretVersions?.length) void qb.whereIn(`${TableName.SecretVersionV2}.version`, secretVersions); - }) - .orWhere((qb) => { - void qb.where(`${TableName.SecretVersionV2}.secretId`, secretId); - void qb.whereNull(`${TableName.Membership}.scopeProjectId`); if (secretVersions?.length) void qb.whereIn(`${TableName.SecretVersionV2}.version`, secretVersions); }) .select( @@ -229,6 +231,7 @@ export const secretVersionV2BridgeDALFactory = (db: TDbClient) => { db.ref("username").withSchema(TableName.Users).as("userActorName"), db.ref("name").withSchema(TableName.Identity).as("identityActorName"), db.ref("id").withSchema(TableName.Membership).as("membershipId"), + db.ref("actorGroupId").withSchema(TableName.Membership).as("groupId"), db.ref("id").withSchema(TableName.SecretTag).as("tagId"), db.ref("color").withSchema(TableName.SecretTag).as("tagColor"), db.ref("slug").withSchema(TableName.SecretTag).as("tagSlug") @@ -256,7 +259,8 @@ export const secretVersionV2BridgeDALFactory = (db: TDbClient) => { ...SecretVersionsV2Schema.parse(el), userActorName: el.userActorName, identityActorName: el.identityActorName, - membershipId: el.membershipId + membershipId: el.membershipId, + groupId: el.groupId }), childrenMapper: [ { diff --git a/docs/docs.json b/docs/docs.json index 6d8eb04cc..3fb6914af 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -784,7 +784,10 @@ "groups": [ { "group": "Infisical PAM", - "pages": ["documentation/platform/pam/overview"] + "pages": [ + "documentation/platform/pam/overview", + "documentation/platform/pam/session-recording" + ] } ] } diff --git a/docs/documentation/guides/organization-structure.mdx b/docs/documentation/guides/organization-structure.mdx index 3cba64678..752c06ccc 100644 --- a/docs/documentation/guides/organization-structure.mdx +++ b/docs/documentation/guides/organization-structure.mdx @@ -24,9 +24,11 @@ Infisical is designed to provide comprehensive, centralized, and efficient manag ### 2. Projects - **Definition and Role**: [Projects](/documentation/platform/project) are the highest-level construct within an [organization](/documentation/platform/organization) in Infisical. They serve as the primary container for all functionalities. -- **Correspondence to Code Repositories**: Projects typically align with specific code repositories. +- **Common Project Mappings**: Projects typically align with applications, services, or code repositories — each being a valid and common approach depending on your organizational structure. - **Functional Capabilities**: Each project encompasses features for managing secrets, certificates, and encryption keys, serving as the central hub for these resources. +Projects are isolated from one another. Secrets, certificates, and other resources cannot be shared or referenced across different projects. Each project maintains its own separate set of resources. + ### 3. Environments - **Purpose**: Environments are designed for organizing and compartmentalizing secrets within projects. @@ -40,8 +42,9 @@ Infisical is designed to provide comprehensive, centralized, and efficient manag ### 5. Imports -- **Purpose and Benefits**: To promote reusability and avoid redundancy, Infisical supports the use of imports. This allows secrets, folders, or entire environments to be referenced across multiple projects as needed. -- **Best Practice**: Utilizing [secret imports](/documentation/platform/secret-reference#secret-imports) or [references](/documentation/platform/secret-reference#secret-referencing) ensures consistency and minimizes manual overhead. +- **Purpose and Benefits**: To promote reusability and avoid redundancy within a project, Infisical supports the use of imports and references. This allows secrets, folders, or entire environments to be referenced within the same project as needed. +- **Project Isolation**: Imports and references only work within a single project. Secrets cannot be imported or referenced across different projects, as projects are isolated from one another. +- **Best Practice**: Utilizing [secret imports](/documentation/platform/secret-reference#secret-imports) or [references](/documentation/platform/secret-reference#secret-referencing) ensures consistency and minimizes manual overhead when managing secrets within a project. ### 6. Approval Workflows diff --git a/docs/documentation/platform/kms/hsm-integration.mdx b/docs/documentation/platform/kms/hsm-integration.mdx index 7a8d15fe5..a2e2dce16 100644 --- a/docs/documentation/platform/kms/hsm-integration.mdx +++ b/docs/documentation/platform/kms/hsm-integration.mdx @@ -30,13 +30,96 @@ Using a hardware security module comes with the added benefit of having a secure Enabling HSM encryption has a set of key benefits: 1. **Root Key Wrapping**: The root KMS encryption key that is used to secure your Infisical instance will be encrypted using the HSM device rather than the standard software-protected key. + #### Caveats - **Performance**: Using an HSM device can have a performance impact on your Infisical instance. This is due to the additional latency introduced by the HSM device. This is however only noticeable when your instance(s) start up or when the encryption strategy is changed. - **Key Recovery**: If the HSM device is lost or destroyed, you will no longer be able to decrypt your data stored within Infisical. Most HSM providers offer recovery options, which you should consider when setting up an HSM device. -### Requirements -- An Infisical instance with a version number that is equal to or greater than `v0.91.0`. -- An HSM device from a provider such as [Thales Luna HSM](https://cpl.thalesgroup.com/encryption/data-protection-on-demand/services/luna-cloud-hsm), [AWS CloudHSM](https://aws.amazon.com/cloudhsm/), [Fortanix HSM](https://www.fortanix.com/platform/data-security-manager), or others. +## Requirements +- An HSM device _(PKCS#11 compatible library)_ from a compatible provider such as [Thales Luna HSM](https://cpl.thalesgroup.com/encryption/data-protection-on-demand/services/luna-cloud-hsm), [AWS CloudHSM](https://aws.amazon.com/cloudhsm/), [Fortanix HSM](https://www.fortanix.com/platform/data-security-manager), or others. + Infisical is validated to work with PKCS#11 2.30 and newer. If your HSM device doesn't follow the >=2.30 PKCS#11 standard you may see degraded performance. + + +## Environment Variable Configuration +To configure your Infisical instance to use an HSM, you must set the required environment variables. Below you'll find an example of the required environment variables. +For further instructions on how to configure the HSM device for your Infisical instance, please see the [Setup Instructions](#setup-instructions) section. + + +```dotenv +HSM_LIB_PATH=/usr/local/lib/cloudhsm/cloudhsm.so +HSM_SLOT=1 +HSM_KEY_LABEL=infisical-key +HSM_PIN=your:pin +``` + +- `HSM_LIB_PATH`: The path to the PKCS#11 library provided by the HSM provider. This usually comes in the form of a `.so` for Linux and MacOS, or a `.dll` file for Windows. For Docker, you need to mount the library path as a volume. Further instructions can be found below. If you are using Docker, make sure to set the HSM_LIB_PATH environment variable to the path where the library is mounted in the container. +- `HSM_PIN`: The PKCS#11 PIN to use for authentication with the HSM device. +- `HSM_SLOT`: The slot number to use for the HSM device. This is typically between `0` and `5` for most HSM devices. +- `HSM_KEY_LABEL`: The label of the key to use for encryption. **Please note that if no key is found with the provided label, the HSM will create a new key with the provided label.** + +You can read more about the [default instance configurations](/self-hosting/configuration/envars) here. + +## PKCS#11 Key Attributes + +If no AES key or HMAC key already exists with the label you defined on the `HSM_KEY_LABEL` environment variable, then Infisical will create one for you automatically using the label specified on `HSM_KEY_LABEL`. +Below you'll find a list of the attributes each key will be created with. + +### AES Key + + + If you bring your own AES key and don't let Infisical create it for you it must have at least the following attributes: + + * `CKA_CLASS`: `CKO_SECRET_KEY` — Defines the key class _(secret key)_. + * `CKA_KEY_TYPE`: `CKO_AES` — Defines the key type _(AES key)_. + * `CKA_VALUE_LEN`: `32` — 256-bit key size. + * `CKA_ENCRYPT`: `true` — Encryption capabilities enabled. + * `CKA_DECRYPT`: `true` — Decryption capabilities enabled. + * `CKA_TOKEN`: `true` — The key material will persist in your HSM so it can be reused. + + + Note that for security reasons it is highly recommended to create an AES key with the full set of key attributes seen below if you're going to bring your own key. + + + +* `CKA_CLASS`: `CKO_SECRET_KEY` — Defines the key class _(secret key)_. +* `CKA_KEY_TYPE`: `CKO_AES` — Defines the key type _(AES key)_. +* `CKA_VALUE_LEN`: `32` — 256-bit key size. +* `CKA_LABEL`: Your specified label in the `HSM_KEY_LABEL` environment variable. +* `CKA_ENCRYPT`: `true` — Encryption capabilities enabled. +* `CKA_DECRYPT`: `true` — Decryption capabilities enabled. +* `CKA_TOKEN`: `true` — The key material will persist in your HSM so it can be reused. +* `CKA_EXTRACTABLE`: `false` — The key material is not extractable from the HSM. +* `CKA_SENSITIVE`: `true` — The key material is marked as sensitive. +* `CKA_PRIVATE`: `true` — The key material is marked as private to the slot and can't be accessed from other slots. + +### HMAC Key + + + If you bring your own HMAC key and don't let Infisical create it for you it must have at least the following attributes: + + * `CKA_CLASS`: `CKO_SECRET_KEY` — Defines the key class _(secret key)_. + * `CKA_KEY_TYPE`: `CKO_GENERIC_SECRET` — Defines the key class _(generic secret key)_. + * `CKA_VALUE_LEN`: `32` — 256-bit key size + * `CKA_SIGN`: `true` — Signing capabilities enabled + * `CKA_VERIFY`: `true` — Verifying capabilities enabled. + * `CKA_TOKEN`: `true` — The key material will persist in your HSM so it can be reused. + + + Note that for security reasons it is highly recommended to create an HMAC key with the full set of key attributes seen below if you're going to bring your own key. + + + +* `CKA_CLASS`: `CKO_SECRET_KEY` — Defines the key class _(secret key)_. +* `CKA_KEY_TYPE`: `CKO_GENERIC_SECRET` — Defines the key class _(generic secret key)_. +* `CKA_VALUE_LEN`: `32` — 256-bit key size. +* `CKA_LABEL`: Your specified label in the `HSM_KEY_LABEL` environment variable, suffixed with `_HMAC`. If you specify `infisical-key-v1`, then the HMAC key label will become `infisical-key-v1_HMAC`. +* `CKA_SIGN`: `true` — Signing capabilities enabled +* `CKA_VERIFY`: `true` — Verifying capabilities enabled. +* `CKA_TOKEN`: `true` — The key material will persist in your HSM so it can be reused. +* `CKA_EXTRACTABLE`: `false` — The key material is not extractable from the HSM. +* `CKA_SENSITIVE`: `true` — The key material is marked as sensitive. +* `CKA_PRIVATE`: `true` — The key material is marked as private to the slot and can't be accessed from other slots. + ## Setup Instructions diff --git a/docs/documentation/platform/pam/session-recording.mdx b/docs/documentation/platform/pam/session-recording.mdx new file mode 100644 index 000000000..7e560d5c2 --- /dev/null +++ b/docs/documentation/platform/pam/session-recording.mdx @@ -0,0 +1,60 @@ +--- +title: "Session Recording" +sidebarTitle: "Session Recording" +description: "Learn how Infisical records and stores session activity for auditing and monitoring." +--- + +Infisical's Privileged Access Management (PAM) provides robust session recording capabilities to help you audit and monitor user activity across your infrastructure. + +## How It Works + +When a user initiates a session through the Infisical Gateway, a recording of the session begins. The gateway securely caches all recording data in temporary encrypted files on its local system. + +Once the session concludes, the gateway transmits the complete recording to the Infisical platform for long-term, centralized storage. This asynchronous process ensures that sessions remain operational even if the connection to the Infisical platform is temporarily lost. After the upload is complete, administrators can search and review the session logs in the Infisical UI. + +## What's Captured + +The content captured during a session depends on the type of resource being accessed. + +### Database Sessions + +For database connections, Infisical captures all queries executed and their corresponding responses. + + +Support for additional resource types like SSH and RDP is coming soon. + + +## Viewing Recordings + +To review session recordings: + +1. Navigate to the **PAM Sessions** page in your project. +2. Click on a session from the list to view its details. + +![PAM Sessions](/images/pam/session-recording/sessions-page.png) + +The session details page provides key information, including the complete session logs, connection status, the user who initiated it, and more. + +![PAM Individual Session](/images/pam/session-recording/individual-session-page.png) + +### Searching Logs + +You can use the search bar to quickly find relevant information: + +- **On the main Sessions page:** Search across all session logs to locate specific queries or outputs. +- **On an individual session page:** Search within that specific session's logs to pinpoint activity. + +![PAM Sessions Search](/images/pam/session-recording/sessions-page-search.png) + +![PAM Individual Session Search](/images/pam/session-recording/individual-session-page-search.png) + +## FAQ + + + + Yes. All session recordings are encrypted at rest by default, ensuring your audit data is always secure. + + + Currently, Infisical uses an asynchronous approach where the gateway records the entire session locally before uploading it. This design makes your PAM sessions more resilient, as they don't depend on a constant, active connection to the Infisical platform. We may introduce live streaming capabilities in a future release. + + diff --git a/docs/images/pam/session-recording/individual-session-page-search.png b/docs/images/pam/session-recording/individual-session-page-search.png new file mode 100644 index 000000000..ce369f515 Binary files /dev/null and b/docs/images/pam/session-recording/individual-session-page-search.png differ diff --git a/docs/images/pam/session-recording/individual-session-page.png b/docs/images/pam/session-recording/individual-session-page.png new file mode 100644 index 000000000..2926caf67 Binary files /dev/null and b/docs/images/pam/session-recording/individual-session-page.png differ diff --git a/docs/images/pam/session-recording/sessions-page-search.png b/docs/images/pam/session-recording/sessions-page-search.png new file mode 100644 index 000000000..a90cda587 Binary files /dev/null and b/docs/images/pam/session-recording/sessions-page-search.png differ diff --git a/docs/images/pam/session-recording/sessions-page.png b/docs/images/pam/session-recording/sessions-page.png new file mode 100644 index 000000000..8faab291d Binary files /dev/null and b/docs/images/pam/session-recording/sessions-page.png differ diff --git a/docs/integrations/app-connections/chef.mdx b/docs/integrations/app-connections/chef.mdx index 60c49fb1f..fdb866557 100644 --- a/docs/integrations/app-connections/chef.mdx +++ b/docs/integrations/app-connections/chef.mdx @@ -3,6 +3,14 @@ title: "Chef Connection" description: "Learn how to configure a Chef Connection for Infisical." --- + + Chef App Connection is a paid feature. + + If you're using Infisical Cloud, then it is available under the **Enterprise Tier**. If you're self-hosting Infisical, + then you should contact team@infisical.com to purchase an enterprise license to use it. + + + Infisical supports the use of User Private Key to connect with Chef Server. Please access your **starter kit** to get all the required information to create a Chef Connection. diff --git a/docs/integrations/platforms/kubernetes-injector.mdx b/docs/integrations/platforms/kubernetes-injector.mdx index b7ecf5815..22262ffbf 100644 --- a/docs/integrations/platforms/kubernetes-injector.mdx +++ b/docs/integrations/platforms/kubernetes-injector.mdx @@ -51,6 +51,27 @@ $ kubectl logs deployment/infisical-agent-injector 2025/05/19 14:20:06 Successfully updated webhook configuration with CA bundle ``` +## Windows support + +The Infisical Agent Injector supports both running on Windows-based pods, and injecting the agent into Windows-based pods. + +To run the agent injector on a Windows pod, it's important that you add the `nodeSelector.kubernetes.io/os` label to the pod's deployment with the value `windows`. +This can be done by changing the helm values.yaml by adding the following: + +```yaml values.yaml +nodeSelector: + kubernetes.io/os: windows +``` + +By default the agent injector will run on Linux-based pods, unless you specify otherwise like in the example above. +No extra configuration is needed to inject into Windows-based pods, as the agent injector will detect and handle the injection automatically. + +The Agent Injector will only run and inject into Windows-based pods that are running on the supported Windows versions: +- **Windows Server 2022** + +We're looking to add support for other Windows versions in the future. If you're using a different Windows version, please let us know by opening [an issue](https://github.com/Infisical/infisical-agent-injector/issues/new), and we'll look into adding support for your desired version as soon as possible. + + ## Supported annotations The Infisical Agent Injector supports the following annotations: diff --git a/docs/integrations/secret-syncs/chef.mdx b/docs/integrations/secret-syncs/chef.mdx index 13f3b3474..423d42b4b 100644 --- a/docs/integrations/secret-syncs/chef.mdx +++ b/docs/integrations/secret-syncs/chef.mdx @@ -3,6 +3,14 @@ title: "Chef Sync" description: "Learn how to configure a Chef Sync for Infisical." --- + + Chef Sync is a paid feature. + + If you're using Infisical Cloud, then it is available under the **Enterprise Tier**. If you're self-hosting Infisical, + then you should contact team@infisical.com to purchase an enterprise license to use it. + + + **Prerequisites:** - Create a [Chef Connection](/integrations/app-connections/chef) diff --git a/docs/self-hosting/guides/monitoring-telemetry.mdx b/docs/self-hosting/guides/monitoring-telemetry.mdx index b23c51b27..763826d4f 100644 --- a/docs/self-hosting/guides/monitoring-telemetry.mdx +++ b/docs/self-hosting/guides/monitoring-telemetry.mdx @@ -27,7 +27,9 @@ Both approaches provide the same metrics data in OTEL format, so you can choose - Access to deploy monitoring services (Prometheus, Grafana, etc.) - Basic understanding of Prometheus and Grafana -## Environment Variables +## Setup + +### Environment Variables Configure the following environment variables in your Infisical backend: @@ -37,287 +39,304 @@ OTEL_TELEMETRY_COLLECTION_ENABLED=true # Choose export type: "prometheus" or "otlp" OTEL_EXPORT_TYPE=prometheus - -# For OTLP push mode, also configure: -# OTEL_EXPORT_OTLP_ENDPOINT=http://otel-collector:4318/v1/metrics -# OTEL_COLLECTOR_BASIC_AUTH_USERNAME=your_collector_username -# OTEL_COLLECTOR_BASIC_AUTH_PASSWORD=your_collector_password -# OTEL_OTLP_PUSH_INTERVAL=30000 ``` -**Note**: The `OTEL_COLLECTOR_BASIC_AUTH_USERNAME` and `OTEL_COLLECTOR_BASIC_AUTH_PASSWORD` values must match the credentials configured in your OpenTelemetry Collector's `basicauth/server` extension. These are not hardcoded values - you configure them in your collector configuration file. + + + This approach exposes metrics on port 9464 at the `/metrics` endpoint, allowing Prometheus to scrape the data. The metrics are exposed in Prometheus format but originate from OpenTelemetry instrumentation. -## Option 1: Pull-based Monitoring (Prometheus) + ### Configuration -This approach exposes metrics on port 9464 at the `/metrics` endpoint, allowing Prometheus to scrape the data. The metrics are exposed in Prometheus format but originate from OpenTelemetry instrumentation. + + +```bash +OTEL_TELEMETRY_COLLECTION_ENABLED=true +OTEL_EXPORT_TYPE=prometheus +``` + -### Configuration + + Expose the metrics port in your Infisical backend: -1. **Enable Prometheus export in Infisical**: + - **Docker**: Expose port 9464 + - **Kubernetes**: Create a service exposing port 9464 + - **Other**: Ensure port 9464 is accessible to your monitoring stack + - ```bash - OTEL_TELEMETRY_COLLECTION_ENABLED=true - OTEL_EXPORT_TYPE=prometheus - ``` - -2. **Expose the metrics port** in your Infisical backend: - - - **Docker**: Expose port 9464 - - **Kubernetes**: Create a service exposing port 9464 - - **Other**: Ensure port 9464 is accessible to your monitoring stack - -3. **Create Prometheus configuration** (`prometheus.yml`): - - ```yaml - global: - scrape_interval: 30s - evaluation_interval: 30s - - scrape_configs: - - job_name: "infisical" - scrape_interval: 30s - static_configs: - - targets: ["infisical-backend:9464"] # Adjust hostname/port based on your deployment - metrics_path: "/metrics" - ``` - - **Note**: Replace `infisical-backend:9464` with the actual hostname and port where your Infisical backend is running. This could be: - - - **Docker Compose**: `infisical-backend:9464` (service name) - - **Kubernetes**: `infisical-backend.default.svc.cluster.local:9464` (service name) - - **Bare Metal**: `192.168.1.100:9464` (actual IP address) - - **Cloud**: `your-infisical.example.com:9464` (domain name) - -### Deployment Options - -#### Docker Compose + +Create `prometheus.yml`: ```yaml -services: +global: + scrape_interval: 30s + evaluation_interval: 30s + +scrape_configs: + - job_name: "infisical" + scrape_interval: 30s + static_configs: + - targets: ["infisical-backend:9464"] # Adjust hostname/port based on your deployment + metrics_path: "/metrics" +``` + + +Replace `infisical-backend:9464` with the actual hostname and port where your Infisical backend is running. This could be: + +- **Docker Compose**: `infisical-backend:9464` (service name) +- **Kubernetes**: `infisical-backend.default.svc.cluster.local:9464` (service name) +- **Bare Metal**: `192.168.1.100:9464` (actual IP address) +- **Cloud**: `your-infisical.example.com:9464` (domain name) + + + + + ### Deployment Options + + Once you've configured Infisical to expose metrics, you'll need to deploy Prometheus to scrape and store them. Below are examples for different deployment environments. Choose the option that matches your infrastructure. + + + + ```yaml + services: + prometheus: + image: prom/prometheus:latest + ports: + - "9090:9090" + volumes: + - ./prometheus.yml:/etc/prometheus/prometheus.yml:ro + command: + - "--config.file=/etc/prometheus/prometheus.yml" + + grafana: + image: grafana/grafana:latest + ports: + - "3000:3000" + environment: + - GF_SECURITY_ADMIN_USER=admin + - GF_SECURITY_ADMIN_PASSWORD=admin + ``` + + + ```yaml + # prometheus-deployment.yaml + apiVersion: apps/v1 + kind: Deployment + metadata: + name: prometheus + spec: + replicas: 1 + selector: + matchLabels: + app: prometheus + template: + metadata: + labels: + app: prometheus + spec: + containers: + - name: prometheus + image: prom/prometheus:latest + ports: + - containerPort: 9090 + volumeMounts: + - name: config + mountPath: /etc/prometheus + volumes: + - name: config + configMap: + name: prometheus-config + + --- + # prometheus-service.yaml + apiVersion: v1 + kind: Service + metadata: + name: prometheus + spec: + selector: + app: prometheus + ports: + - port: 9090 + targetPort: 9090 + type: ClusterIP + ``` + + + ```bash + helm repo add prometheus-community https://prometheus-community.github.io/helm-charts + helm install prometheus prometheus-community/prometheus \ + --set server.config.global.scrape_interval=30s \ + --set server.config.scrape_configs[0].job_name=infisical \ + --set server.config.scrape_configs[0].static_configs[0].targets[0]=infisical-backend:9464 + ``` + + + + + + This approach sends metrics directly to an OpenTelemetry Collector via the OTLP protocol. This gives you the most flexibility as you can configure the collector to export to multiple backends simultaneously. + + ### Configuration + + + +```bash +OTEL_TELEMETRY_COLLECTION_ENABLED=true +OTEL_EXPORT_TYPE=otlp +OTEL_EXPORT_OTLP_ENDPOINT=http://otel-collector:4318/v1/metrics +OTEL_COLLECTOR_BASIC_AUTH_USERNAME=infisical +OTEL_COLLECTOR_BASIC_AUTH_PASSWORD=infisical +OTEL_OTLP_PUSH_INTERVAL=30000 +``` + + + +Create `otel-collector-config.yaml`: + +```yaml +extensions: + health_check: + pprof: + zpages: + basicauth/server: + htpasswd: + inline: | + your_username:your_password + +receivers: + otlp: + protocols: + http: + endpoint: 0.0.0.0:4318 + auth: + authenticator: basicauth/server + prometheus: - image: prom/prometheus:latest - ports: - - "9090:9090" - volumes: - - ./prometheus.yml:/etc/prometheus/prometheus.yml:ro - command: - - "--config.file=/etc/prometheus/prometheus.yml" + config: + scrape_configs: + - job_name: otel-collector + scrape_interval: 30s + static_configs: + - targets: [infisical-backend:9464] + metric_relabel_configs: + - action: labeldrop + regex: "service_instance_id|service_name" - grafana: - image: grafana/grafana:latest - ports: - - "3000:3000" - environment: - - GF_SECURITY_ADMIN_USER=admin - - GF_SECURITY_ADMIN_PASSWORD=admin +processors: + batch: + +exporters: + prometheus: + endpoint: "0.0.0.0:8889" + auth: + authenticator: basicauth/server + resource_to_telemetry_conversion: + enabled: true + +service: + extensions: [basicauth/server, health_check, pprof, zpages] + pipelines: + metrics: + receivers: [otlp] + processors: [batch] + exporters: [prometheus] ``` -#### Kubernetes + +Replace `your_username:your_password` with your chosen credentials. These must match the values you set in Infisical's `OTEL_COLLECTOR_BASIC_AUTH_USERNAME` and `OTEL_COLLECTOR_BASIC_AUTH_PASSWORD` environment variables. + + + + +Create Prometheus configuration for the collector: ```yaml -# prometheus-deployment.yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: prometheus -spec: - replicas: 1 - selector: - matchLabels: - app: prometheus - template: - metadata: - labels: - app: prometheus - spec: - containers: - - name: prometheus - image: prom/prometheus:latest - ports: - - containerPort: 9090 - volumeMounts: - - name: config - mountPath: /etc/prometheus - volumes: - - name: config - configMap: - name: prometheus-config +global: + scrape_interval: 30s + evaluation_interval: 30s ---- -# prometheus-service.yaml -apiVersion: v1 -kind: Service -metadata: - name: prometheus -spec: - selector: - app: prometheus - ports: - - port: 9090 - targetPort: 9090 - type: ClusterIP +scrape_configs: + - job_name: "otel-collector" + scrape_interval: 30s + static_configs: + - targets: ["otel-collector:8889"] # Adjust hostname/port based on your deployment + metrics_path: "/metrics" ``` -#### Helm + +Replace `otel-collector:8889` with the actual hostname and port where your OpenTelemetry Collector is running. This could be: -```bash -helm repo add prometheus-community https://prometheus-community.github.io/helm-charts -helm install prometheus prometheus-community/prometheus \ - --set server.config.global.scrape_interval=30s \ - --set server.config.scrape_configs[0].job_name=infisical \ - --set server.config.scrape_configs[0].static_configs[0].targets[0]=infisical-backend:9464 -``` +- **Docker Compose**: `otel-collector:8889` (service name) +- **Kubernetes**: `otel-collector.default.svc.cluster.local:8889` (service name) +- **Bare Metal**: `192.168.1.100:8889` (actual IP address) +- **Cloud**: `your-collector.example.com:8889` (domain name) + + + -## Option 2: Push-based Monitoring (OTLP) + ### Deployment Options -This approach sends metrics directly to an OpenTelemetry Collector via the OTLP protocol. This gives you the most flexibility as you can configure the collector to export to multiple backends simultaneously. + After configuring Infisical and the OpenTelemetry Collector, you'll need to deploy the collector to receive metrics from Infisical. Below are examples for different deployment environments. Choose the option that matches your infrastructure. -### Configuration + + + ```yaml + services: + otel-collector: + image: otel/opentelemetry-collector-contrib:latest + ports: + - 4318:4318 # OTLP http receiver + - 8889:8889 # Prometheus exporter metrics + volumes: + - ./otel-collector-config.yaml:/etc/otelcol-contrib/config.yaml:ro + command: + - "--config=/etc/otelcol-contrib/config.yaml" + ``` + + + ```yaml + # otel-collector-deployment.yaml + apiVersion: apps/v1 + kind: Deployment + metadata: + name: otel-collector + spec: + replicas: 1 + selector: + matchLabels: + app: otel-collector + template: + metadata: + labels: + app: otel-collector + spec: + containers: + - name: otel-collector + image: otel/opentelemetry-collector-contrib:latest + ports: + - containerPort: 4318 + - containerPort: 8889 + volumeMounts: + - name: config + mountPath: /etc/otelcol-contrib + volumes: + - name: config + configMap: + name: otel-collector-config + ``` + + + ```bash + helm repo add open-telemetry https://open-telemetry.github.io/opentelemetry-helm-charts + helm install otel-collector open-telemetry/opentelemetry-collector \ + --set config.receivers.otlp.protocols.http.endpoint=0.0.0.0:4318 \ + --set config.exporters.prometheus.endpoint=0.0.0.0:8889 + ``` + + -1. **Enable OTLP export in Infisical**: - - ```bash - OTEL_TELEMETRY_COLLECTION_ENABLED=true - OTEL_EXPORT_TYPE=otlp - OTEL_EXPORT_OTLP_ENDPOINT=http://otel-collector:4318/v1/metrics - OTEL_COLLECTOR_BASIC_AUTH_USERNAME=infisical - OTEL_COLLECTOR_BASIC_AUTH_PASSWORD=infisical - OTEL_OTLP_PUSH_INTERVAL=30000 - ``` - -2. **Create OpenTelemetry Collector configuration** (`otel-collector-config.yaml`): - - ```yaml - extensions: - health_check: - pprof: - zpages: - basicauth/server: - htpasswd: - inline: | - your_username:your_password - - receivers: - otlp: - protocols: - http: - endpoint: 0.0.0.0:4318 - auth: - authenticator: basicauth/server - - prometheus: - config: - scrape_configs: - - job_name: otel-collector - scrape_interval: 30s - static_configs: - - targets: [infisical-backend:9464] - metric_relabel_configs: - - action: labeldrop - regex: "service_instance_id|service_name" - - processors: - batch: - - exporters: - prometheus: - endpoint: "0.0.0.0:8889" - auth: - authenticator: basicauth/server - resource_to_telemetry_conversion: - enabled: true - - service: - extensions: [basicauth/server, health_check, pprof, zpages] - pipelines: - metrics: - receivers: [otlp] - processors: [batch] - exporters: [prometheus] - ``` - - **Important**: Replace `your_username:your_password` with your chosen credentials. These must match the values you set in Infisical's `OTEL_COLLECTOR_BASIC_AUTH_USERNAME` and `OTEL_COLLECTOR_BASIC_AUTH_PASSWORD` environment variables. - -3. **Create Prometheus configuration** for the collector: - - ```yaml - global: - scrape_interval: 30s - evaluation_interval: 30s - - scrape_configs: - - job_name: "otel-collector" - scrape_interval: 30s - static_configs: - - targets: ["otel-collector:8889"] # Adjust hostname/port based on your deployment - metrics_path: "/metrics" - ``` - - **Note**: Replace `otel-collector:8889` with the actual hostname and port where your OpenTelemetry Collector is running. This could be: - - - **Docker Compose**: `otel-collector:8889` (service name) - - **Kubernetes**: `otel-collector.default.svc.cluster.local:8889` (service name) - - **Bare Metal**: `192.168.1.100:8889` (actual IP address) - - **Cloud**: `your-collector.example.com:8889` (domain name) - -### Deployment Options - -#### Docker Compose - -```yaml -services: - otel-collector: - image: otel/opentelemetry-collector-contrib:latest - ports: - - 4318:4318 # OTLP http receiver - - 8889:8889 # Prometheus exporter metrics - volumes: - - ./otel-collector-config.yaml:/etc/otelcol-contrib/config.yaml:ro - command: - - "--config=/etc/otelcol-contrib/config.yaml" -``` - -#### Kubernetes - -```yaml -# otel-collector-deployment.yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: otel-collector -spec: - replicas: 1 - selector: - matchLabels: - app: otel-collector - template: - metadata: - labels: - app: otel-collector - spec: - containers: - - name: otel-collector - image: otel/opentelemetry-collector-contrib:latest - ports: - - containerPort: 4318 - - containerPort: 8889 - volumeMounts: - - name: config - mountPath: /etc/otelcol-contrib - volumes: - - name: config - configMap: - name: otel-collector-config -``` - -#### Helm - -```bash -helm repo add open-telemetry https://open-telemetry.github.io/opentelemetry-helm-charts -helm install otel-collector open-telemetry/opentelemetry-collector \ - --set config.receivers.otlp.protocols.http.endpoint=0.0.0.0:4318 \ - --set config.exporters.prometheus.endpoint=0.0.0.0:8889 -``` + + ## Available Metrics @@ -327,166 +346,211 @@ Infisical exposes the following key metrics in OpenTelemetry format: These metrics track all HTTP API requests to Infisical, including request counts, latency, and errors. Use these to monitor overall API health, identify performance bottlenecks, and track usage patterns across users and machine identities. -#### Total API Requests + + + **Metric Name**: `infisical.http.server.request.count` -- **Metric Name**: `infisical.http.server.request.count` -- **Type**: Counter -- **Unit**: `{request}` -- **Description**: Total number of API requests to Infisical (covers both human users and machine identities) -- **Attributes**: - - `infisical.organization.id` (string): Organization ID - - `infisical.organization.name` (string): Organization name (e.g., "Platform Engineering Team") - - `infisical.user.id` (string, optional): User ID if human user - - `infisical.user.email` (string, optional): User email (e.g., "jane.doe@cisco.com") - - `infisical.identity.id` (string, optional): Machine identity ID - - `infisical.identity.name` (string, optional): Machine identity name (e.g., "prod-k8s-operator") - - `infisical.auth.method` (string, optional): Auth method used - - `http.request.method` (string): HTTP method (GET, POST, PUT, DELETE) - - `http.route` (string): API endpoint route pattern - - `http.response.status_code` (int): HTTP status code - - `infisical.project.id` (string, optional): Project ID - - `infisical.project.name` (string, optional): Project name - - `user_agent.original` (string, optional): User agent string - - `client.address` (string, optional): IP address + **Type**: Counter -#### Request Duration + **Unit**: `{request}` -- **Metric Name**: `infisical.http.server.request.duration` -- **Type**: Histogram -- **Unit**: `s` (seconds) -- **Description**: API request latency -- **Buckets**: [0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10] -- **Attributes**: - - `infisical.organization.id` (string): Organization ID - - `infisical.organization.name` (string): Organization name - - `infisical.user.id` (string, optional): User ID if human user - - `infisical.user.email` (string, optional): User email - - `infisical.identity.id` (string, optional): Machine identity ID - - `infisical.identity.name` (string, optional): Machine identity name - - `http.request.method` (string): HTTP method - - `http.route` (string): API endpoint route pattern - - `http.response.status_code` (int): HTTP status code - - `infisical.project.id` (string, optional): Project ID - - `infisical.project.name` (string, optional): Project name + **Description**: Total number of API requests to Infisical (covers both human users and machine identities) -#### API Errors by Actor + **Attributes**: + - `infisical.organization.id` (string): Organization ID + - `infisical.organization.name` (string): Organization name (e.g., "Platform Engineering Team") + - `infisical.user.id` (string, optional): User ID if human user + - `infisical.user.email` (string, optional): User email (e.g., "jane.doe@cisco.com") + - `infisical.identity.id` (string, optional): Machine identity ID + - `infisical.identity.name` (string, optional): Machine identity name (e.g., "prod-k8s-operator") + - `infisical.auth.method` (string, optional): Auth method used + - `http.request.method` (string): HTTP method (GET, POST, PUT, DELETE) + - `http.route` (string): API endpoint route pattern + - `http.response.status_code` (int): HTTP status code + - `infisical.project.id` (string, optional): Project ID + - `infisical.project.name` (string, optional): Project name + - `user_agent.original` (string, optional): User agent string + - `client.address` (string, optional): IP address + -- **Metric Name**: `infisical.http.server.error.count` -- **Type**: Counter -- **Unit**: `{error}` -- **Description**: API errors grouped by actor (for identifying misconfigured services) -- **Attributes**: - - `infisical.organization.id` (string): Organization ID - - `infisical.organization.name` (string): Organization name - - `infisical.user.id` (string, optional): User ID if human - - `infisical.user.email` (string, optional): User email - - `infisical.identity.id` (string, optional): Identity ID if machine - - `infisical.identity.name` (string, optional): Identity name - - `http.route` (string): API endpoint where error occurred - - `http.request.method` (string): HTTP method - - `error.type` (string): Error category/type (client_error, server_error, auth_error, rate_limit_error, etc.) - - `infisical.project.id` (string, optional): Project ID - - `infisical.project.name` (string, optional): Project name - - `client.address` (string, optional): IP address - - `user_agent.original` (string, optional): User agent information + + **Metric Name**: `infisical.http.server.request.duration` + + **Type**: Histogram + + **Unit**: `s` (seconds) + + **Description**: API request latency + + **Buckets**: [0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10] + + **Attributes**: + - `infisical.organization.id` (string): Organization ID + - `infisical.organization.name` (string): Organization name + - `infisical.user.id` (string, optional): User ID if human user + - `infisical.user.email` (string, optional): User email + - `infisical.identity.id` (string, optional): Machine identity ID + - `infisical.identity.name` (string, optional): Machine identity name + - `http.request.method` (string): HTTP method + - `http.route` (string): API endpoint route pattern + - `http.response.status_code` (int): HTTP status code + - `infisical.project.id` (string, optional): Project ID + - `infisical.project.name` (string, optional): Project name + + + + **Metric Name**: `infisical.http.server.error.count` + + **Type**: Counter + + **Unit**: `{error}` + + **Description**: API errors grouped by actor (for identifying misconfigured services) + + **Attributes**: + - `infisical.organization.id` (string): Organization ID + - `infisical.organization.name` (string): Organization name + - `infisical.user.id` (string, optional): User ID if human + - `infisical.user.email` (string, optional): User email + - `infisical.identity.id` (string, optional): Identity ID if machine + - `infisical.identity.name` (string, optional): Identity name + - `http.route` (string): API endpoint where error occurred + - `http.request.method` (string): HTTP method + - `error.type` (string): Error category/type (client_error, server_error, auth_error, rate_limit_error, etc.) + - `infisical.project.id` (string, optional): Project ID + - `infisical.project.name` (string, optional): Project name + - `client.address` (string, optional): IP address + - `user_agent.original` (string, optional): User agent information + + ### Secret Operations Metrics These metrics provide visibility into secret access patterns, helping you understand which secrets are being accessed, by whom, and from where. Essential for security auditing and access pattern analysis. -#### Secret Read Operations - -- **Metric Name**: `infisical.secret.read.count` -- **Type**: Counter -- **Unit**: `{operation}` -- **Description**: Number of secret read operations -- **Attributes**: - - `infisical.organization.id` (string): Organization ID - - `infisical.organization.name` (string): Organization name - - `infisical.project.id` (string): Project ID - - `infisical.project.name` (string): Project name (e.g., "payment-service-secrets") - - `infisical.environment` (string): Environment (dev, staging, prod) - - `infisical.secret.path` (string): Path to secrets (e.g., "/microservice-a/database") - - `infisical.secret.name` (string, optional): Name of secret - - `infisical.user.id` (string, optional): User ID if human - - `infisical.user.email` (string, optional): User email - - `infisical.identity.id` (string, optional): Machine identity ID - - `infisical.identity.name` (string, optional): Machine identity name - - `user_agent.original` (string, optional): User agent/SDK information - - `client.address` (string, optional): IP address + + + **Metric Name**: `infisical.secret.read.count` + + **Type**: Counter + + **Unit**: `{operation}` + + **Description**: Number of secret read operations + + **Attributes**: + - `infisical.organization.id` (string): Organization ID + - `infisical.organization.name` (string): Organization name + - `infisical.project.id` (string): Project ID + - `infisical.project.name` (string): Project name (e.g., "payment-service-secrets") + - `infisical.environment` (string): Environment (dev, staging, prod) + - `infisical.secret.path` (string): Path to secrets (e.g., "/microservice-a/database") + - `infisical.secret.name` (string, optional): Name of secret + - `infisical.user.id` (string, optional): User ID if human + - `infisical.user.email` (string, optional): User email + - `infisical.identity.id` (string, optional): Machine identity ID + - `infisical.identity.name` (string, optional): Machine identity name + - `user_agent.original` (string, optional): User agent/SDK information + - `client.address` (string, optional): IP address + + ### Authentication Metrics These metrics track authentication attempts and outcomes, enabling you to monitor login success rates, detect potential security threats, and identify authentication issues. -#### Login Attempts - -- **Metric Name**: `infisical.auth.attempt.count` -- **Type**: Counter -- **Unit**: `{attempt}` -- **Description**: Authentication attempts (both successful and failed) -- **Attributes**: - - `infisical.organization.id` (string): Organization ID - - `infisical.organization.name` (string): Organization name - - `infisical.user.id` (string, optional): User ID if human (if identifiable) - - `infisical.user.email` (string, optional): User email (if identifiable) - - `infisical.identity.id` (string, optional): Identity ID if machine (if identifiable) - - `infisical.identity.name` (string, optional): Identity name (if identifiable) - - `infisical.auth.method` (string): Authentication method attempted - - `infisical.auth.result` (string): success or failure - - `error.type` (string, optional): Reason for failure if failed (invalid_credentials, expired_token, invalid_token, etc.) - - `client.address` (string): IP address - - `user_agent.original` (string, optional): User agent/client information - - `infisical.auth.attempt.username` (string, optional): Attempted username/email (if available) - -### Legacy Metrics - -These metrics are from the previous instrumentation and may be deprecated in future versions. Consider migrating to the new Core API Metrics for more comprehensive observability. - -- `API_latency` - API request latency histogram in milliseconds (Labels: `route`, `method`, `statusCode`) -- `API_errors` - API error count histogram (Labels: `route`, `method`, `type`, `name`) + + + **Metric Name**: `infisical.auth.attempt.count` + + **Type**: Counter + + **Unit**: `{attempt}` + + **Description**: Authentication attempts (both successful and failed) + + **Attributes**: + - `infisical.organization.id` (string): Organization ID + - `infisical.organization.name` (string): Organization name + - `infisical.user.id` (string, optional): User ID if human (if identifiable) + - `infisical.user.email` (string, optional): User email (if identifiable) + - `infisical.identity.id` (string, optional): Identity ID if machine (if identifiable) + - `infisical.identity.name` (string, optional): Identity name (if identifiable) + - `infisical.auth.method` (string): Authentication method attempted + - `infisical.auth.result` (string): success or failure + - `error.type` (string, optional): Reason for failure if failed (invalid_credentials, expired_token, invalid_token, etc.) + - `client.address` (string): IP address + - `user_agent.original` (string, optional): User agent/client information + - `infisical.auth.attempt.username` (string, optional): Attempted username/email (if available) + + ### Integration & Secret Sync Metrics These metrics monitor secret synchronization operations between Infisical and external systems, helping you track sync health, identify integration failures, and troubleshoot connectivity issues. -- `integration_secret_sync_errors` - Integration secret sync error count + + + Integration secret sync error count - - **Labels**: `version`, `integration`, `integrationId`, `type`, `status`, `name`, `projectId` - - **Example**: Monitor integration sync failures across different services + - **Labels**: `version`, `integration`, `integrationId`, `type`, `status`, `name`, `projectId` + - **Example**: Monitor integration sync failures across different services + -- `secret_sync_sync_secrets_errors` - Secret sync operation error count + + Secret sync operation error count - - **Labels**: `version`, `destination`, `syncId`, `projectId`, `type`, `status`, `name` - - **Example**: Track secret sync failures to external systems + - **Labels**: `version`, `destination`, `syncId`, `projectId`, `type`, `status`, `name` + - **Example**: Track secret sync failures to external systems + -- `secret_sync_import_secrets_errors` - Secret import operation error count + + Secret import operation error count - - **Labels**: `version`, `destination`, `syncId`, `projectId`, `type`, `status`, `name` - - **Example**: Monitor secret import failures + - **Labels**: `version`, `destination`, `syncId`, `projectId`, `type`, `status`, `name` + - **Example**: Monitor secret import failures + -- `secret_sync_remove_secrets_errors` - Secret removal operation error count - - **Labels**: `version`, `destination`, `syncId`, `projectId`, `type`, `status`, `name` - - **Example**: Track secret removal operation failures + + Secret removal operation error count + + - **Labels**: `version`, `destination`, `syncId`, `projectId`, `type`, `status`, `name` + - **Example**: Track secret removal operation failures + + ### System Metrics These low-level HTTP metrics are automatically collected by OpenTelemetry's instrumentation layer, providing baseline performance data for all HTTP traffic. -- `http_server_duration` - HTTP server request duration metrics (histogram buckets, count, sum) -- `http_client_duration` - HTTP client request duration metrics (histogram buckets, count, sum) + + + HTTP server request duration metrics (histogram buckets, count, sum) + + + + HTTP client request duration metrics (histogram buckets, count, sum) + + ## Troubleshooting -### Common Issues + + If your metrics are not showing up in Prometheus or your monitoring system, check the following: -1. **Metrics not appearing**: + - Verify `OTEL_TELEMETRY_COLLECTION_ENABLED=true` is set in your Infisical environment variables + - Ensure the correct `OTEL_EXPORT_TYPE` is set (`prometheus` or `otlp`) + - Check network connectivity between Infisical and your monitoring services (Prometheus or OTLP collector) + - For pull-based monitoring: Verify port 9464 is exposed and accessible + - For push-based monitoring: Verify the OTLP endpoint URL is correct and reachable + - Check Infisical backend logs for any errors related to metrics export + - - Check if `OTEL_TELEMETRY_COLLECTION_ENABLED=true` - - Verify the correct `OTEL_EXPORT_TYPE` is set - - Check network connectivity between services + + If you're experiencing authentication errors with the OpenTelemetry Collector: -2. **Authentication errors**: - - - Verify basic auth credentials in OTLP configuration - - Check if credentials match between Infisical and collector + - Verify basic auth credentials in your OTLP configuration match between Infisical and the collector + - Check that `OTEL_COLLECTOR_BASIC_AUTH_USERNAME` and `OTEL_COLLECTOR_BASIC_AUTH_PASSWORD` match the credentials in your `otel-collector-config.yaml` + - Ensure the htpasswd format in the collector configuration is correct + - Test the collector endpoint manually using curl with the same credentials to verify they work + diff --git a/frontend/src/components/features/WishForm.tsx b/frontend/src/components/features/WishForm.tsx index 118900bc9..28107809a 100644 --- a/frontend/src/components/features/WishForm.tsx +++ b/frontend/src/components/features/WishForm.tsx @@ -35,23 +35,16 @@ export const WishForm = () => { const [isOpen, setIsOpen] = useToggle(false); const createWish = async (data: TFormData) => { - try { - await mutateAsync({ - text: data.text - }); + await mutateAsync({ + text: data.text + }); - createNotification({ - text: "Your wish has been sent to the Infisical team!", - type: "success" - }); + createNotification({ + text: "Your wish has been sent to the Infisical team!", + type: "success" + }); - setIsOpen.off(); - } catch { - createNotification({ - text: "An error occured while sending your wish to the Infisical team.", - type: "error" - }); - } + setIsOpen.off(); }; return ( diff --git a/frontend/src/components/mfa/TotpRegistration.tsx b/frontend/src/components/mfa/TotpRegistration.tsx index 0b79bfd98..bcb0d3691 100644 --- a/frontend/src/components/mfa/TotpRegistration.tsx +++ b/frontend/src/components/mfa/TotpRegistration.tsx @@ -25,27 +25,20 @@ const TotpRegistration = ({ onComplete, shouldCenterQr }: Props) => { const handleTotpVerify = async (event: React.FormEvent) => { event.preventDefault(); - try { - const result = await verifyUserTotp({ - totp - }); + const result = await verifyUserTotp({ + totp + }); - createNotification({ - text: "Successfully configured mobile authenticator", - type: "success" - }); + createNotification({ + text: "Successfully configured mobile authenticator", + type: "success" + }); - if (result.recoveryCodes && result.recoveryCodes.length > 0) { - setRecoveryCodes(result.recoveryCodes); - setShowRecoveryModal(true); - } else if (onComplete) { - onComplete(); - } - } catch { - createNotification({ - text: "Failed to verify TOTP code", - type: "error" - }); + if (result.recoveryCodes && result.recoveryCodes.length > 0) { + setRecoveryCodes(result.recoveryCodes); + setShowRecoveryModal(true); + } else if (onComplete) { + onComplete(); } }; diff --git a/frontend/src/components/organization/CreateOrgModal/CreateOrgModal.tsx b/frontend/src/components/organization/CreateOrgModal/CreateOrgModal.tsx index 23c3fe6a5..84931f84a 100644 --- a/frontend/src/components/organization/CreateOrgModal/CreateOrgModal.tsx +++ b/frontend/src/components/organization/CreateOrgModal/CreateOrgModal.tsx @@ -43,35 +43,27 @@ export const CreateOrgModal: FC = ({ isOpen, onClose }) => const { mutateAsync: selectOrg } = useSelectOrganization(); const onFormSubmit = async ({ name }: FormData) => { - try { - const organization = await createOrg({ - name - }); + const organization = await createOrg({ + name + }); - await selectOrg({ - organizationId: organization.id - }); + await selectOrg({ + organizationId: organization.id + }); - createNotification({ - text: "Successfully created organization", - type: "success" - }); + createNotification({ + text: "Successfully created organization", + type: "success" + }); - navigate({ - to: "/organization/projects" - }); + navigate({ + to: "/organization/projects" + }); - localStorage.setItem("orgData.id", organization.id); + localStorage.setItem("orgData.id", organization.id); - reset(); - onClose(); - } catch (err) { - console.error(err); - createNotification({ - text: "Failed to created organization", - type: "error" - }); - } + reset(); + onClose(); }; return ( diff --git a/frontend/src/components/pki-syncs/DeletePkiSyncModal.tsx b/frontend/src/components/pki-syncs/DeletePkiSyncModal.tsx index e465d3f34..c01efcbf2 100644 --- a/frontend/src/components/pki-syncs/DeletePkiSyncModal.tsx +++ b/frontend/src/components/pki-syncs/DeletePkiSyncModal.tsx @@ -20,28 +20,19 @@ export const DeletePkiSyncModal = ({ isOpen, onOpenChange, pkiSync, onComplete } const handleDeletePkiSync = async () => { const destinationName = PKI_SYNC_MAP[destination].name; - try { - await deleteSync.mutateAsync({ - syncId, - projectId, - destination - }); + await deleteSync.mutateAsync({ + syncId, + projectId, + destination + }); - createNotification({ - text: `Successfully deleted ${destinationName} PKI Sync`, - type: "success" - }); + createNotification({ + text: `Successfully deleted ${destinationName} PKI Sync`, + type: "success" + }); - if (onComplete) onComplete(); - onOpenChange(false); - } catch (err) { - console.error(err); - - createNotification({ - text: `Failed to delete ${destinationName} PKI Sync`, - type: "error" - }); - } + if (onComplete) onComplete(); + onOpenChange(false); }; return ( diff --git a/frontend/src/components/pki-syncs/PkiSyncImportCertificatesModal.tsx b/frontend/src/components/pki-syncs/PkiSyncImportCertificatesModal.tsx index 33b06dbe4..43192c5e3 100644 --- a/frontend/src/components/pki-syncs/PkiSyncImportCertificatesModal.tsx +++ b/frontend/src/components/pki-syncs/PkiSyncImportCertificatesModal.tsx @@ -21,27 +21,18 @@ const Content = ({ pkiSync, onComplete }: ContentProps) => { const triggerImportCertificates = useTriggerPkiSyncImportCertificates(); const handleTriggerImportCertificates = async () => { - try { - await triggerImportCertificates.mutateAsync({ - syncId, - destination, - projectId - }); + await triggerImportCertificates.mutateAsync({ + syncId, + destination, + projectId + }); - createNotification({ - text: `Successfully triggered certificate import for ${destinationName} Sync`, - type: "success" - }); + createNotification({ + text: `Successfully triggered certificate import for ${destinationName} Sync`, + type: "success" + }); - onComplete(); - } catch (err) { - console.error(err); - - createNotification({ - text: `Failed to trigger certificate import for ${destinationName} Sync`, - type: "error" - }); - } + onComplete(); }; return ( diff --git a/frontend/src/components/pki-syncs/PkiSyncRemoveCertificatesModal.tsx b/frontend/src/components/pki-syncs/PkiSyncRemoveCertificatesModal.tsx index f17855289..cee845381 100644 --- a/frontend/src/components/pki-syncs/PkiSyncRemoveCertificatesModal.tsx +++ b/frontend/src/components/pki-syncs/PkiSyncRemoveCertificatesModal.tsx @@ -21,27 +21,18 @@ const Content = ({ pkiSync, onComplete }: ContentProps) => { const triggerRemoveCertificates = useTriggerPkiSyncRemoveCertificates(); const handleTriggerRemoveCertificates = async () => { - try { - await triggerRemoveCertificates.mutateAsync({ - syncId, - destination, - projectId - }); + await triggerRemoveCertificates.mutateAsync({ + syncId, + destination, + projectId + }); - createNotification({ - text: `Successfully triggered certificate removal for ${destinationName} Sync`, - type: "success" - }); + createNotification({ + text: `Successfully triggered certificate removal for ${destinationName} Sync`, + type: "success" + }); - onComplete(); - } catch (err) { - console.error(err); - - createNotification({ - text: `Failed to trigger certificate removal for ${destinationName} Sync`, - type: "error" - }); - } + onComplete(); }; return ( diff --git a/frontend/src/components/pki-syncs/forms/CreatePkiSyncForm.tsx b/frontend/src/components/pki-syncs/forms/CreatePkiSyncForm.tsx index 6ffb2f859..1dee6eaa7 100644 --- a/frontend/src/components/pki-syncs/forms/CreatePkiSyncForm.tsx +++ b/frontend/src/components/pki-syncs/forms/CreatePkiSyncForm.tsx @@ -86,14 +86,8 @@ export const CreatePkiSyncForm = ({ destination, onComplete, onCancel, initialDa type: "success" }); onComplete(pkiSync); - } catch (err: Error | unknown) { - console.error("PKI sync creation failed:", err); + } catch { setShowConfirmation(false); - createNotification({ - title: `Failed to create ${destinationName} Certificate Sync`, - text: err instanceof Error ? err.message : "An unknown error occurred", - type: "error" - }); } }; diff --git a/frontend/src/components/pki-syncs/forms/EditPkiSyncForm.tsx b/frontend/src/components/pki-syncs/forms/EditPkiSyncForm.tsx index 137e0d6de..9041d32f2 100644 --- a/frontend/src/components/pki-syncs/forms/EditPkiSyncForm.tsx +++ b/frontend/src/components/pki-syncs/forms/EditPkiSyncForm.tsx @@ -42,28 +42,19 @@ export const EditPkiSyncForm = ({ pkiSync, fields, onComplete }: Props) => { }); const onSubmit = async ({ connection, ...formData }: TUpdatePkiSyncForm) => { - try { - const updatedPkiSync = await updatePkiSync.mutateAsync({ - syncId: pkiSync.id, - ...formData, - connectionId: connection.id, - projectId: pkiSync.projectId, - destination: pkiSync.destination - }); + const updatedPkiSync = await updatePkiSync.mutateAsync({ + syncId: pkiSync.id, + ...formData, + connectionId: connection.id, + projectId: pkiSync.projectId, + destination: pkiSync.destination + }); - createNotification({ - text: `Successfully updated ${destinationName} PKI Sync`, - type: "success" - }); - onComplete(updatedPkiSync); - } catch (err: any) { - console.error(err); - createNotification({ - title: `Failed to update ${destinationName} PKI Sync`, - text: err.message, - type: "error" - }); - } + createNotification({ + text: `Successfully updated ${destinationName} PKI Sync`, + type: "success" + }); + onComplete(updatedPkiSync); }; let Component: ReactNode; diff --git a/frontend/src/components/project/ProjectOverviewChangeSection.tsx b/frontend/src/components/project/ProjectOverviewChangeSection.tsx index 548fbd1e3..455b0806a 100644 --- a/frontend/src/components/project/ProjectOverviewChangeSection.tsx +++ b/frontend/src/components/project/ProjectOverviewChangeSection.tsx @@ -56,30 +56,22 @@ export const ProjectOverviewChangeSection = ({ showSlugField = false }: Props) = }, [currentProject, showSlugField]); const onFormSubmit = async (data: BaseFormData | FormDataWithSlug) => { - try { - if (!currentProject?.id) return; + if (!currentProject?.id) return; - await mutateAsync({ - projectId: currentProject.id, - newProjectName: data.name, - newProjectDescription: data.description, - ...(showSlugField && - "slug" in data && { - newSlug: data.slug !== currentProject.slug ? data.slug : undefined - }) - }); + await mutateAsync({ + projectId: currentProject.id, + newProjectName: data.name, + newProjectDescription: data.description, + ...(showSlugField && + "slug" in data && { + newSlug: data.slug !== currentProject.slug ? data.slug : undefined + }) + }); - createNotification({ - text: "Successfully updated project overview", - type: "success" - }); - } catch (err) { - console.error(err); - createNotification({ - text: "Failed to update project overview", - type: "error" - }); - } + createNotification({ + text: "Successfully updated project overview", + type: "success" + }); }; return ( diff --git a/frontend/src/components/projects/NewProjectModal.tsx b/frontend/src/components/projects/NewProjectModal.tsx index d71e7b957..663d6a0b7 100644 --- a/frontend/src/components/projects/NewProjectModal.tsx +++ b/frontend/src/components/projects/NewProjectModal.tsx @@ -141,29 +141,24 @@ const NewProjectForm = ({ onOpenChange }: NewProjectFormProps) => { // type check if (!currentOrg) return; if (!user) return; - try { - const { - data: { project } - } = await createWs.mutateAsync({ - projectName: name, - projectDescription: description, - kmsKeyId: kmsKeyId !== INTERNAL_KMS_KEY_ID ? kmsKeyId : undefined, - template, - type - }); - await refetchWorkspaces(); + const { + data: { project } + } = await createWs.mutateAsync({ + projectName: name, + projectDescription: description, + kmsKeyId: kmsKeyId !== INTERNAL_KMS_KEY_ID ? kmsKeyId : undefined, + template, + type + }); + await refetchWorkspaces(); - createNotification({ text: "Project created", type: "success" }); - reset(); - onOpenChange(false); - navigate({ - to: getProjectHomePage(project.type, project.environments), - params: { projectId: project.id } - }); - } catch (err) { - console.error(err); - createNotification({ text: "Failed to create project", type: "error" }); - } + createNotification({ text: "Project created", type: "success" }); + reset(); + onOpenChange(false); + navigate({ + to: getProjectHomePage(project.type, project.environments), + params: { projectId: project.id } + }); }; const onSubmit = handleSubmit((data) => { return onCreateProject(data); diff --git a/frontend/src/components/secret-rotations-v2/DeleteSecretRotationV2Modal.tsx b/frontend/src/components/secret-rotations-v2/DeleteSecretRotationV2Modal.tsx index 20b08eb49..524c66933 100644 --- a/frontend/src/components/secret-rotations-v2/DeleteSecretRotationV2Modal.tsx +++ b/frontend/src/components/secret-rotations-v2/DeleteSecretRotationV2Modal.tsx @@ -37,29 +37,22 @@ export const DeleteSecretRotationV2Modal = ({ const handleDeleteSecretRotation = async () => { const rotationType = SECRET_ROTATION_MAP[type].name; - try { - await deleteSecretRotation.mutateAsync({ - rotationId, - type, - revokeGeneratedCredentials, - deleteSecrets, - projectId, - secretPath: folder.path - }); + await deleteSecretRotation.mutateAsync({ + rotationId, + type, + revokeGeneratedCredentials, + deleteSecrets, + projectId, + secretPath: folder.path + }); - createNotification({ - text: `Successfully deleted ${rotationType} Rotation`, - type: "success" - }); + createNotification({ + text: `Successfully deleted ${rotationType} Rotation`, + type: "success" + }); - if (onComplete) onComplete(); - onOpenChange(false); - } catch { - createNotification({ - text: `Failed to delete ${rotationType} Rotation`, - type: "error" - }); - } + if (onComplete) onComplete(); + onOpenChange(false); }; return ( diff --git a/frontend/src/components/secret-rotations-v2/RotateSecretRotationV2Modal.tsx b/frontend/src/components/secret-rotations-v2/RotateSecretRotationV2Modal.tsx index e2c931d49..7ad9611be 100644 --- a/frontend/src/components/secret-rotations-v2/RotateSecretRotationV2Modal.tsx +++ b/frontend/src/components/secret-rotations-v2/RotateSecretRotationV2Modal.tsx @@ -22,28 +22,19 @@ const Content = ({ secretRotation, onComplete }: ContentProps) => { const rotationType = SECRET_ROTATION_MAP[type].name; const handleRotateSecrets = async () => { - try { - await rotateSecrets.mutateAsync({ - rotationId, - type, - projectId, - secretPath: folder.path - }); + await rotateSecrets.mutateAsync({ + rotationId, + type, + projectId, + secretPath: folder.path + }); - createNotification({ - text: `Successfully rotated ${rotationType} secrets`, - type: "success" - }); + createNotification({ + text: `Successfully rotated ${rotationType} secrets`, + type: "success" + }); - onComplete(); - } catch (err) { - console.error(err); - - createNotification({ - text: `Failed to rotate ${rotationType} secrets`, - type: "error" - }); - } + onComplete(); }; return ( diff --git a/frontend/src/components/secret-rotations-v2/forms/SecretRotationV2Form.tsx b/frontend/src/components/secret-rotations-v2/forms/SecretRotationV2Form.tsx index 9887da026..320793ed1 100644 --- a/frontend/src/components/secret-rotations-v2/forms/SecretRotationV2Form.tsx +++ b/frontend/src/components/secret-rotations-v2/forms/SecretRotationV2Form.tsx @@ -120,21 +120,13 @@ export const SecretRotationV2Form = ({ environment: environment.slug, projectId: currentProject.id }); - try { - const rotation = await mutation; + const rotation = await mutation; - createNotification({ - text: `Successfully ${secretRotation ? "updated" : "created"} ${rotationType} Rotation`, - type: "success" - }); - onComplete(rotation); - } catch (err: any) { - createNotification({ - title: `Failed to ${secretRotation ? "update" : "create"} ${rotationType} Rotation`, - text: err.message, - type: "error" - }); - } + createNotification({ + text: `Successfully ${secretRotation ? "updated" : "created"} ${rotationType} Rotation`, + type: "success" + }); + onComplete(rotation); }; const handlePrev = () => { diff --git a/frontend/src/components/secret-scanning/DeleteSecretScanningDataSourceModal.tsx b/frontend/src/components/secret-scanning/DeleteSecretScanningDataSourceModal.tsx index 9cf918dfb..091de4cc0 100644 --- a/frontend/src/components/secret-scanning/DeleteSecretScanningDataSourceModal.tsx +++ b/frontend/src/components/secret-scanning/DeleteSecretScanningDataSourceModal.tsx @@ -28,26 +28,19 @@ export const DeleteSecretScanningDataSourceModal = ({ const handleDeleteDataSource = async () => { const dataSourceType = SECRET_SCANNING_DATA_SOURCE_MAP[type].name; - try { - await deleteDataSource.mutateAsync({ - dataSourceId, - type, - projectId - }); + await deleteDataSource.mutateAsync({ + dataSourceId, + type, + projectId + }); - createNotification({ - text: `Successfully deleted ${dataSourceType} Data Source`, - type: "success" - }); + createNotification({ + text: `Successfully deleted ${dataSourceType} Data Source`, + type: "success" + }); - if (onComplete) onComplete(); - onOpenChange(false); - } catch { - createNotification({ - text: `Failed to delete ${dataSourceType} Data Source`, - type: "error" - }); - } + if (onComplete) onComplete(); + onOpenChange(false); }; return ( diff --git a/frontend/src/components/secret-scanning/forms/SecretScanningDataSourceForm.tsx b/frontend/src/components/secret-scanning/forms/SecretScanningDataSourceForm.tsx index 4d5ccdc79..563f82d46 100644 --- a/frontend/src/components/secret-scanning/forms/SecretScanningDataSourceForm.tsx +++ b/frontend/src/components/secret-scanning/forms/SecretScanningDataSourceForm.tsx @@ -73,21 +73,13 @@ export const SecretScanningDataSourceForm = ({ connectionId: connection?.id, projectId: currentProject.id }); - try { - const source = await mutation; + const source = await mutation; - createNotification({ - text: `Successfully ${source ? "updated" : "created"} ${sourceType} Data Source`, - type: "success" - }); - onComplete(source); - } catch (err: any) { - createNotification({ - title: `Failed to ${dataSource ? "update" : "create"} ${sourceType} Data Source`, - text: err.message, - type: "error" - }); - } + createNotification({ + text: `Successfully ${source ? "updated" : "created"} ${sourceType} Data Source`, + type: "success" + }); + onComplete(source); }; const handlePrev = () => { diff --git a/frontend/src/components/secret-syncs/DeleteSecretSyncModal.tsx b/frontend/src/components/secret-syncs/DeleteSecretSyncModal.tsx index 2b3903a9b..de8b2e79d 100644 --- a/frontend/src/components/secret-syncs/DeleteSecretSyncModal.tsx +++ b/frontend/src/components/secret-syncs/DeleteSecretSyncModal.tsx @@ -23,29 +23,20 @@ export const DeleteSecretSyncModal = ({ isOpen, onOpenChange, secretSync, onComp const handleDeleteSecretSync = async () => { const destinationName = SECRET_SYNC_MAP[destination].name; - try { - await deleteSync.mutateAsync({ - syncId, - destination, - removeSecrets, - projectId - }); + await deleteSync.mutateAsync({ + syncId, + destination, + removeSecrets, + projectId + }); - createNotification({ - text: `Successfully removed ${destinationName} Sync`, - type: "success" - }); + createNotification({ + text: `Successfully removed ${destinationName} Sync`, + type: "success" + }); - if (onComplete) onComplete(); - onOpenChange(false); - } catch (err) { - console.error(err); - - createNotification({ - text: `Failed to remove ${destinationName} Sync`, - type: "error" - }); - } + if (onComplete) onComplete(); + onOpenChange(false); }; return ( diff --git a/frontend/src/components/secret-syncs/SecretSyncImportSecretsModal.tsx b/frontend/src/components/secret-syncs/SecretSyncImportSecretsModal.tsx index c1b21a771..656faffeb 100644 --- a/frontend/src/components/secret-syncs/SecretSyncImportSecretsModal.tsx +++ b/frontend/src/components/secret-syncs/SecretSyncImportSecretsModal.tsx @@ -51,28 +51,19 @@ const Content = ({ secretSync, onComplete }: ContentProps) => { const triggerImportSecrets = useTriggerSecretSyncImportSecrets(); const handleTriggerImportSecrets = async ({ importBehavior }: TFormData) => { - try { - await triggerImportSecrets.mutateAsync({ - syncId, - destination, - importBehavior, - projectId - }); + await triggerImportSecrets.mutateAsync({ + syncId, + destination, + importBehavior, + projectId + }); - createNotification({ - text: `Successfully triggered secret import for ${destinationName} Sync`, - type: "success" - }); + createNotification({ + text: `Successfully triggered secret import for ${destinationName} Sync`, + type: "success" + }); - onComplete(); - } catch (err) { - console.error(err); - - createNotification({ - text: `Failed to trigger secret import for ${destinationName} Sync`, - type: "error" - }); - } + onComplete(); }; return ( diff --git a/frontend/src/components/secret-syncs/SecretSyncRemoveSecretsModal.tsx b/frontend/src/components/secret-syncs/SecretSyncRemoveSecretsModal.tsx index 718392b92..9c9c0e659 100644 --- a/frontend/src/components/secret-syncs/SecretSyncRemoveSecretsModal.tsx +++ b/frontend/src/components/secret-syncs/SecretSyncRemoveSecretsModal.tsx @@ -21,27 +21,18 @@ const Content = ({ secretSync, onComplete }: ContentProps) => { const triggerSyncImport = useTriggerSecretSyncRemoveSecrets(); const handleTriggerRemoveSecrets = async () => { - try { - await triggerSyncImport.mutateAsync({ - syncId, - destination, - projectId - }); + await triggerSyncImport.mutateAsync({ + syncId, + destination, + projectId + }); - createNotification({ - text: `Successfully triggered secret removal for ${destinationName} Sync`, - type: "success" - }); + createNotification({ + text: `Successfully triggered secret removal for ${destinationName} Sync`, + type: "success" + }); - onComplete(); - } catch (err) { - console.error(err); - - createNotification({ - text: `Failed to trigger secret removal for ${destinationName} Sync`, - type: "error" - }); - } + onComplete(); }; return ( diff --git a/frontend/src/components/secret-syncs/forms/CreateSecretSyncForm.tsx b/frontend/src/components/secret-syncs/forms/CreateSecretSyncForm.tsx index ebad86cbd..21a69b163 100644 --- a/frontend/src/components/secret-syncs/forms/CreateSecretSyncForm.tsx +++ b/frontend/src/components/secret-syncs/forms/CreateSecretSyncForm.tsx @@ -88,14 +88,8 @@ export const CreateSecretSyncForm = ({ type: "success" }); onComplete(secretSync); - } catch (err: any) { - console.error(err); + } catch { setShowConfirmation(false); - createNotification({ - title: `Failed to add ${destinationName} Sync`, - text: err.message, - type: "error" - }); } }; diff --git a/frontend/src/components/secret-syncs/forms/EditSecretSyncForm.tsx b/frontend/src/components/secret-syncs/forms/EditSecretSyncForm.tsx index 2085afe9c..207b72cd8 100644 --- a/frontend/src/components/secret-syncs/forms/EditSecretSyncForm.tsx +++ b/frontend/src/components/secret-syncs/forms/EditSecretSyncForm.tsx @@ -58,29 +58,20 @@ export const EditSecretSyncForm = ({ secretSync, fields, onComplete }: Props) => const performUpdate = useCallback( async (formData: TSecretSyncForm) => { - try { - const { environment, connection, ...updateData } = formData; - const updatedSecretSync = await updateSecretSync.mutateAsync({ - syncId: secretSync.id, - ...updateData, - environment: environment?.slug, - connectionId: connection.id, - projectId: secretSync.projectId - }); + const { environment, connection, ...updateData } = formData; + const updatedSecretSync = await updateSecretSync.mutateAsync({ + syncId: secretSync.id, + ...updateData, + environment: environment?.slug, + connectionId: connection.id, + projectId: secretSync.projectId + }); - createNotification({ - text: `Successfully updated ${destinationName} Sync`, - type: "success" - }); - onComplete(updatedSecretSync); - } catch (err: any) { - console.error(err); - createNotification({ - title: `Failed to update ${destinationName} Sync`, - text: err.message, - type: "error" - }); - } + createNotification({ + text: `Successfully updated ${destinationName} Sync`, + type: "success" + }); + onComplete(updatedSecretSync); }, [updateSecretSync, secretSync.id, secretSync.projectId, destinationName, onComplete] ); diff --git a/frontend/src/components/tags/CreateTagModal/CreateTagModal.tsx b/frontend/src/components/tags/CreateTagModal/CreateTagModal.tsx index 3c38926af..97e74cae4 100644 --- a/frontend/src/components/tags/CreateTagModal/CreateTagModal.tsx +++ b/frontend/src/components/tags/CreateTagModal/CreateTagModal.tsx @@ -130,26 +130,18 @@ export const CreateTagModal = ({ isOpen, onToggle, append, currentSecret }: Prop }, [isOpen]); const onFormSubmit = async ({ slug, color }: FormData) => { - try { - const data = await createWsTag({ - projectId, - tagColor: color, - tagSlug: slug - }); - append(data); - onToggle(false); - reset(); - createNotification({ - text: "Successfully created a tag", - type: "success" - }); - } catch (error) { - console.error(error); - createNotification({ - text: "Failed to create a tag", - type: "error" - }); - } + const data = await createWsTag({ + projectId, + tagColor: color, + tagSlug: slug + }); + append(data); + onToggle(false); + reset(); + createNotification({ + text: "Successfully created a tag", + type: "success" + }); }; return ( diff --git a/frontend/src/components/v2/HighlightText/HighlightText.tsx b/frontend/src/components/v2/HighlightText/HighlightText.tsx index c81dab2df..92fdc1d6d 100644 --- a/frontend/src/components/v2/HighlightText/HighlightText.tsx +++ b/frontend/src/components/v2/HighlightText/HighlightText.tsx @@ -9,22 +9,10 @@ export const HighlightText = ({ }) => { if (!text) return null; - const renderTextWithNewlines = (input: string, baseKeyPrefix: string = ""): React.ReactNode[] => { - if (!input) return []; - const lines = input.split("\n"); - return lines.flatMap((line, index) => { - const nodes: React.ReactNode[] = [line]; - if (index < lines.length - 1) { - nodes.push(
); - } - return nodes; - }); - }; - const searchTerm = highlight.toLowerCase().trim(); if (!searchTerm) { - return {renderTextWithNewlines(text, "full-text")}; + return {text}; } const parts: React.ReactNode[] = []; @@ -36,16 +24,12 @@ export const HighlightText = ({ text.replace(regex, (match: string, offset: number) => { if (offset > lastIndex) { const preMatchText = text.substring(lastIndex, offset); - parts.push( - - {renderTextWithNewlines(preMatchText, `pre-${lastIndex}`)} - - ); + parts.push({preMatchText}); } parts.push( - {renderTextWithNewlines(match, `match-${offset}`)} + {match} ); @@ -56,11 +40,7 @@ export const HighlightText = ({ if (lastIndex < text.length) { const postMatchText = text.substring(lastIndex); - parts.push( - - {renderTextWithNewlines(postMatchText, `post-${lastIndex}`)} - - ); + parts.push({postMatchText}); } return parts; diff --git a/frontend/src/helpers/appConnections.ts b/frontend/src/helpers/appConnections.ts index 1d0d7bec3..b27da2441 100644 --- a/frontend/src/helpers/appConnections.ts +++ b/frontend/src/helpers/appConnections.ts @@ -131,7 +131,7 @@ export const APP_CONNECTION_MAP: Record< image: "Laravel Forge.png", size: 65 }, - [AppConnection.Chef]: { name: "Chef", image: "Chef.png" } + [AppConnection.Chef]: { name: "Chef", image: "Chef.png", enterprise: true } }; export const getAppConnectionMethodDetails = (method: TAppConnection["method"]) => { diff --git a/frontend/src/hooks/api/ca/types.ts b/frontend/src/hooks/api/ca/types.ts index 696e72494..31d35e904 100644 --- a/frontend/src/hooks/api/ca/types.ts +++ b/frontend/src/hooks/api/ca/types.ts @@ -159,8 +159,8 @@ export type TCreateCertificateDTO = { ttl: string; // string compatible with ms notBefore?: string; notAfter?: string; - keyUsages: CertKeyUsage[]; - extendedKeyUsages: CertExtendedKeyUsage[]; + keyUsages: string[]; + extendedKeyUsages: string[]; }; export type TCreateCertificateResponse = { diff --git a/frontend/src/hooks/api/certificateTemplates/mutations.tsx b/frontend/src/hooks/api/certificateTemplates/mutations.tsx index 0355d9d87..998194ddc 100644 --- a/frontend/src/hooks/api/certificateTemplates/mutations.tsx +++ b/frontend/src/hooks/api/certificateTemplates/mutations.tsx @@ -90,7 +90,12 @@ export const useCreateCertTemplateV2 = () => { return data.certificateTemplate; }, onSuccess: (_, { projectId }) => { - queryClient.invalidateQueries({ queryKey: certTemplateKeys.listTemplates({ projectId }) }); + queryClient.invalidateQueries({ + predicate: (query) => { + const [firstKey, queryProjectId] = query.queryKey; + return firstKey === "list-template" && queryProjectId === projectId; + } + }); } }); }; @@ -107,7 +112,12 @@ export const useUpdateCertTemplateV2 = () => { return data.certificateTemplate; }, onSuccess: (_, { projectId }) => { - queryClient.invalidateQueries({ queryKey: certTemplateKeys.listTemplates({ projectId }) }); + queryClient.invalidateQueries({ + predicate: (query) => { + const [firstKey, queryProjectId] = query.queryKey; + return firstKey === "list-template" && queryProjectId === projectId; + } + }); } }); }; @@ -127,7 +137,12 @@ export const useDeleteCertTemplateV2 = () => { return data.certificateTemplate; }, onSuccess: (_, { projectId }) => { - queryClient.invalidateQueries({ queryKey: certTemplateKeys.listTemplates({ projectId }) }); + queryClient.invalidateQueries({ + predicate: (query) => { + const [firstKey, queryProjectId] = query.queryKey; + return firstKey === "list-template" && queryProjectId === projectId; + } + }); } }); }; diff --git a/frontend/src/hooks/api/secrets/types.ts b/frontend/src/hooks/api/secrets/types.ts index 4f912fad2..f4bf2da98 100644 --- a/frontend/src/hooks/api/secrets/types.ts +++ b/frontend/src/hooks/api/secrets/types.ts @@ -109,6 +109,7 @@ export type SecretVersions = { actorType?: string | null; name?: string | null; membershipId?: string | null; + groupId?: string | null; } | null; }; diff --git a/frontend/src/layouts/OrganizationLayout/components/NavBar/NewSubOrganizationForm.tsx b/frontend/src/layouts/OrganizationLayout/components/NavBar/NewSubOrganizationForm.tsx index 75041a69e..bfea2e788 100644 --- a/frontend/src/layouts/OrganizationLayout/components/NavBar/NewSubOrganizationForm.tsx +++ b/frontend/src/layouts/OrganizationLayout/components/NavBar/NewSubOrganizationForm.tsx @@ -36,28 +36,21 @@ export const NewSubOrganizationForm = ({ onClose }: ContentProps) => { const router = useRouter(); const onSubmit = async ({ name }: FormData) => { - try { - const { organization } = await createSubOrg.mutateAsync({ - name - }); + const { organization } = await createSubOrg.mutateAsync({ + name + }); - createNotification({ - type: "success", - text: "Successfully created sub organization" - }); - onClose(); + createNotification({ + type: "success", + text: "Successfully created sub organization" + }); + onClose(); - navigate({ - to: "/organization/projects", - search: (prev) => ({ ...prev, subOrganization: organization.name }) - }); - await router.invalidate({ sync: true }).catch(() => null); - } catch { - createNotification({ - text: "Failed to create sub organization", - type: "error" - }); - } + navigate({ + to: "/organization/projects", + search: (prev) => ({ ...prev, subOrganization: organization.name }) + }); + await router.invalidate({ sync: true }).catch(() => null); }; return ( diff --git a/frontend/src/layouts/ProjectLayout/components/ProjectSelect/ProjectSelect.tsx b/frontend/src/layouts/ProjectLayout/components/ProjectSelect/ProjectSelect.tsx index a32cb5093..dcb50b5d2 100644 --- a/frontend/src/layouts/ProjectLayout/components/ProjectSelect/ProjectSelect.tsx +++ b/frontend/src/layouts/ProjectLayout/components/ProjectSelect/ProjectSelect.tsx @@ -11,7 +11,6 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { Link, linkOptions } from "@tanstack/react-router"; import { UpgradePlanModal } from "@app/components/license/UpgradePlanModal"; -import { createNotification } from "@app/components/notifications"; import { OrgPermissionCan } from "@app/components/permissions"; import { NewProjectModal } from "@app/components/projects"; import { @@ -59,31 +58,17 @@ export const ProjectSelect = () => { const { mutateAsync: updateUserProjectFavorites } = useUpdateUserProjectFavorites(); const addProjectToFavorites = async (projectId: string) => { - try { - await updateUserProjectFavorites({ - orgId: currentOrg!.id, - projectFavorites: [...(projectFavorites || []), projectId] - }); - } catch { - createNotification({ - text: "Failed to add project to favorites.", - type: "error" - }); - } + await updateUserProjectFavorites({ + orgId: currentOrg!.id, + projectFavorites: [...(projectFavorites || []), projectId] + }); }; const removeProjectFromFavorites = async (projectId: string) => { - try { - await updateUserProjectFavorites({ - orgId: currentOrg!.id, - projectFavorites: [...(projectFavorites || []).filter((entry) => entry !== projectId)] - }); - } catch { - createNotification({ - text: "Failed to remove project from favorites.", - type: "error" - }); - } + await updateUserProjectFavorites({ + orgId: currentOrg!.id, + projectFavorites: [...(projectFavorites || []).filter((entry) => entry !== projectId)] + }); }; const isAddingProjectsAllowed = subscription?.workspaceLimit diff --git a/frontend/src/pages/admin/AccessManagementPage/components/AddServerAdminModal.tsx b/frontend/src/pages/admin/AccessManagementPage/components/AddServerAdminModal.tsx index 3e7638627..63ec2fa44 100644 --- a/frontend/src/pages/admin/AccessManagementPage/components/AddServerAdminModal.tsx +++ b/frontend/src/pages/admin/AccessManagementPage/components/AddServerAdminModal.tsx @@ -65,20 +65,13 @@ const Content = ({ onClose }: ContentProps) => { const users = usersData.filter((user) => !user.superAdmin); const onSubmit = async ({ user }: FormData) => { - try { - await grantAdmin.mutateAsync(user.id); + await grantAdmin.mutateAsync(user.id); - createNotification({ - type: "success", - text: "Successfully granted server admin status" - }); - onClose(); - } catch { - createNotification({ - text: "Failed to grant server admin status", - type: "error" - }); - } + createNotification({ + type: "success", + text: "Successfully granted server admin status" + }); + onClose(); }; return ( diff --git a/frontend/src/pages/admin/AccessManagementPage/components/ServerAdminsTable.tsx b/frontend/src/pages/admin/AccessManagementPage/components/ServerAdminsTable.tsx index 0ec5c9e58..58516be39 100644 --- a/frontend/src/pages/admin/AccessManagementPage/components/ServerAdminsTable.tsx +++ b/frontend/src/pages/admin/AccessManagementPage/components/ServerAdminsTable.tsx @@ -303,18 +303,11 @@ export const ServerAdminsTable = () => { const handleRemoveUser = async () => { const { id } = popUp?.removeUser?.data as { id: string; username: string }; - try { - await deleteUser(id); - createNotification({ - type: "success", - text: "Successfully deleted user" - }); - } catch { - createNotification({ - type: "error", - text: "Error deleting user" - }); - } + await deleteUser(id); + createNotification({ + type: "success", + text: "Successfully deleted user" + }); handlePopUpClose("removeUser"); }; @@ -322,39 +315,25 @@ export const ServerAdminsTable = () => { const handleRemoveServerAdminAccess = async () => { const { id } = popUp?.removeServerAdmin?.data as { id: string; username: string }; - try { - await removeAdminAccess(id); - createNotification({ - type: "success", - text: "Successfully removed server admin access from user" - }); - } catch { - createNotification({ - type: "error", - text: "Error removing server admin access from user" - }); - } + await removeAdminAccess(id); + createNotification({ + type: "success", + text: "Successfully removed server admin access from user" + }); handlePopUpClose("removeServerAdmin"); }; const handleRemoveUsers = async () => { - try { - await deleteUsers(selectedUsers.map((user) => user.id)); + await deleteUsers(selectedUsers.map((user) => user.id)); - createNotification({ - text: "Successfully removed users", - type: "success" - }); + createNotification({ + text: "Successfully removed users", + type: "success" + }); - setSelectedUsers([]); - handlePopUpClose("removeUsers"); - } catch { - createNotification({ - text: "Failed to remove users", - type: "error" - }); - } + setSelectedUsers([]); + handlePopUpClose("removeUsers"); }; return ( diff --git a/frontend/src/pages/admin/AuthenticationPage/components/AuthenticationPageForm.tsx b/frontend/src/pages/admin/AuthenticationPage/components/AuthenticationPageForm.tsx index 2abb96e60..f8ca30c52 100644 --- a/frontend/src/pages/admin/AuthenticationPage/components/AuthenticationPageForm.tsx +++ b/frontend/src/pages/admin/AuthenticationPage/components/AuthenticationPageForm.tsx @@ -54,59 +54,51 @@ export const AuthenticationPageForm = () => { }); const onAuthFormSubmit = async (formData: TAuthForm) => { - try { - const enabledMethods: LoginMethod[] = []; - if (formData.isEmailEnabled) { - enabledMethods.push(LoginMethod.EMAIL); - } + const enabledMethods: LoginMethod[] = []; + if (formData.isEmailEnabled) { + enabledMethods.push(LoginMethod.EMAIL); + } - if (formData.isGoogleEnabled) { - enabledMethods.push(LoginMethod.GOOGLE); - } + if (formData.isGoogleEnabled) { + enabledMethods.push(LoginMethod.GOOGLE); + } - if (formData.isGithubEnabled) { - enabledMethods.push(LoginMethod.GITHUB); - } + if (formData.isGithubEnabled) { + enabledMethods.push(LoginMethod.GITHUB); + } - if (formData.isGitlabEnabled) { - enabledMethods.push(LoginMethod.GITLAB); - } + if (formData.isGitlabEnabled) { + enabledMethods.push(LoginMethod.GITLAB); + } - if (formData.isSamlEnabled) { - enabledMethods.push(LoginMethod.SAML); - } + if (formData.isSamlEnabled) { + enabledMethods.push(LoginMethod.SAML); + } - if (formData.isLdapEnabled) { - enabledMethods.push(LoginMethod.LDAP); - } + if (formData.isLdapEnabled) { + enabledMethods.push(LoginMethod.LDAP); + } - if (formData.isOidcEnabled) { - enabledMethods.push(LoginMethod.OIDC); - } + if (formData.isOidcEnabled) { + enabledMethods.push(LoginMethod.OIDC); + } - if (!enabledMethods.length) { - createNotification({ - type: "error", - text: "At least one login method should be enabled." - }); - return; - } - - await updateServerConfig({ - enabledLoginMethods: enabledMethods - }); - - createNotification({ - text: "Login methods have been successfully updated.", - type: "success" - }); - } catch (e) { - console.error(e); + if (!enabledMethods.length) { createNotification({ type: "error", - text: "Failed to update login methods." + text: "At least one login method should be enabled." }); + return; } + + await updateServerConfig({ + enabledLoginMethods: enabledMethods + }); + + createNotification({ + text: "Login methods have been successfully updated.", + type: "success" + }); }; return ( diff --git a/frontend/src/pages/admin/CachingPage/components/CachingPageForm.tsx b/frontend/src/pages/admin/CachingPage/components/CachingPageForm.tsx index fbf956b7b..e9bdc3d1e 100644 --- a/frontend/src/pages/admin/CachingPage/components/CachingPageForm.tsx +++ b/frontend/src/pages/admin/CachingPage/components/CachingPageForm.tsx @@ -31,15 +31,10 @@ export const CachingPageForm = () => { const handleInvalidateCacheSubmit = async () => { if (!type || isInvalidating) return; - try { - await invalidateCache({ type }); - createNotification({ text: `Began invalidating ${type} cache`, type: "success" }); - setShouldPoll(true); - handlePopUpClose("invalidateCache"); - } catch (err) { - console.error(err); - createNotification({ text: `Failed to invalidate ${type} cache`, type: "error" }); - } + await invalidateCache({ type }); + createNotification({ text: `Began invalidating ${type} cache`, type: "success" }); + setShouldPoll(true); + handlePopUpClose("invalidateCache"); }; useEffect(() => { diff --git a/frontend/src/pages/admin/EncryptionPage/components/EncryptionPageForm.tsx b/frontend/src/pages/admin/EncryptionPage/components/EncryptionPageForm.tsx index aa7fdbdbb..5121face1 100644 --- a/frontend/src/pages/admin/EncryptionPage/components/EncryptionPageForm.tsx +++ b/frontend/src/pages/admin/EncryptionPage/components/EncryptionPageForm.tsx @@ -60,19 +60,12 @@ export const EncryptionPageForm = () => { return; } - try { - await updateEncryptionStrategy(formData.encryptionStrategy); + await updateEncryptionStrategy(formData.encryptionStrategy); - createNotification({ - type: "success", - text: "Encryption strategy updated successfully" - }); - } catch { - createNotification({ - type: "error", - text: "Failed to update encryption strategy" - }); - } + createNotification({ + type: "success", + text: "Encryption strategy updated successfully" + }); }, []); return ( diff --git a/frontend/src/pages/admin/EnvironmentPage/components/EnvironmentPageForm.tsx b/frontend/src/pages/admin/EnvironmentPage/components/EnvironmentPageForm.tsx index 5f74593a3..8361aa944 100644 --- a/frontend/src/pages/admin/EnvironmentPage/components/EnvironmentPageForm.tsx +++ b/frontend/src/pages/admin/EnvironmentPage/components/EnvironmentPageForm.tsx @@ -176,31 +176,19 @@ export const EnvironmentPageForm = () => { const onSubmit = useCallback( async (formData: TForm) => { - try { - const filteredFormData = Object.fromEntries( - Object.entries(formData).filter(([, value]) => value !== "") - ); - await updateServerConfig({ - envOverrides: filteredFormData - }); + const filteredFormData = Object.fromEntries( + Object.entries(formData).filter(([, value]) => value !== "") + ); + await updateServerConfig({ + envOverrides: filteredFormData + }); - createNotification({ - type: "success", - text: "Environment overrides updated successfully. It can take up to 5 minutes to take effect." - }); + createNotification({ + type: "success", + text: "Environment overrides updated successfully. It can take up to 5 minutes to take effect." + }); - reset(formData); - } catch (error) { - const errorMessage = - (error as any)?.response?.data?.message || - (error as any)?.message || - "An unknown error occurred"; - createNotification({ - type: "error", - title: "Failed to update environment overrides", - text: errorMessage - }); - } + reset(formData); }, [reset, updateServerConfig] ); diff --git a/frontend/src/pages/admin/GeneralPage/components/GeneralPageForm.tsx b/frontend/src/pages/admin/GeneralPage/components/GeneralPageForm.tsx index be92dd679..eff3e3cf8 100644 --- a/frontend/src/pages/admin/GeneralPage/components/GeneralPageForm.tsx +++ b/frontend/src/pages/admin/GeneralPage/components/GeneralPageForm.tsx @@ -68,37 +68,29 @@ export const GeneralPageForm = () => { const organizations = useGetOrganizations(); const onFormSubmit = async (formData: TDashboardForm) => { - try { - const { - allowedSignUpDomain, - trustSamlEmails, - trustLdapEmails, - trustOidcEmails, - authConsentContent, - pageFrameContent - } = formData; + const { + allowedSignUpDomain, + trustSamlEmails, + trustLdapEmails, + trustOidcEmails, + authConsentContent, + pageFrameContent + } = formData; - await updateServerConfig({ - defaultAuthOrgId: defaultAuthOrgId || null, - allowSignUp: signUpMode !== SignUpModes.Disabled, - allowedSignUpDomain: signUpMode === SignUpModes.Anyone ? allowedSignUpDomain : null, - trustSamlEmails, - trustLdapEmails, - trustOidcEmails, - authConsentContent, - pageFrameContent - }); - createNotification({ - text: "Successfully changed sign up setting.", - type: "success" - }); - } catch (e) { - console.error(e); - createNotification({ - type: "error", - text: "Failed to update sign up setting." - }); - } + await updateServerConfig({ + defaultAuthOrgId: defaultAuthOrgId || null, + allowSignUp: signUpMode !== SignUpModes.Disabled, + allowedSignUpDomain: signUpMode === SignUpModes.Anyone ? allowedSignUpDomain : null, + trustSamlEmails, + trustLdapEmails, + trustOidcEmails, + authConsentContent, + pageFrameContent + }); + createNotification({ + text: "Successfully changed sign up setting.", + type: "success" + }); }; return ( diff --git a/frontend/src/pages/admin/GeneralPage/components/UsageReportSection.tsx b/frontend/src/pages/admin/GeneralPage/components/UsageReportSection.tsx index d05800996..663aa18b7 100644 --- a/frontend/src/pages/admin/GeneralPage/components/UsageReportSection.tsx +++ b/frontend/src/pages/admin/GeneralPage/components/UsageReportSection.tsx @@ -10,23 +10,15 @@ export const UsageReportSection = () => { const generateUsageReport = useGenerateUsageReport(); const handleGenerateReport = async () => { - try { - const response = await generateUsageReport.mutateAsync(); - const { csvContent, filename } = response; + const response = await generateUsageReport.mutateAsync(); + const { csvContent, filename } = response; - downloadFile(csvContent, filename, "text/csv"); + downloadFile(csvContent, filename, "text/csv"); - createNotification({ - text: `Usage report downloaded: "${filename}"`, - type: "success" - }); - } catch (error) { - console.error("Failed to generate usage report:", error); - createNotification({ - text: "Failed to generate usage report. Please try again.", - type: "error" - }); - } + createNotification({ + text: `Usage report downloaded: "${filename}"`, + type: "success" + }); }; return ( diff --git a/frontend/src/pages/admin/ResourceOverviewPage/components/AddOrganizationModal.tsx b/frontend/src/pages/admin/ResourceOverviewPage/components/AddOrganizationModal.tsx index d577998b5..48983496f 100644 --- a/frontend/src/pages/admin/ResourceOverviewPage/components/AddOrganizationModal.tsx +++ b/frontend/src/pages/admin/ResourceOverviewPage/components/AddOrganizationModal.tsx @@ -81,25 +81,18 @@ const Content = ({ onClose }: ContentProps) => { const { users = [] } = data ?? {}; const onSubmit = async ({ name, invitees }: FormData) => { - try { - await createOrg.mutateAsync({ - name, - inviteAdminEmails: invitees - .filter((user) => Boolean(user.email)) - .map((user) => user.email) as string[] - }); + await createOrg.mutateAsync({ + name, + inviteAdminEmails: invitees + .filter((user) => Boolean(user.email)) + .map((user) => user.email) as string[] + }); - createNotification({ - type: "success", - text: "Successfully created organization" - }); - onClose(); - } catch { - createNotification({ - text: "Failed to create organization", - type: "error" - }); - } + createNotification({ + type: "success", + text: "Successfully created organization" + }); + onClose(); }; const { append } = useFieldArray({ control, name: "invitees" }); diff --git a/frontend/src/pages/admin/ResourceOverviewPage/components/MachineIdentitiesTable.tsx b/frontend/src/pages/admin/ResourceOverviewPage/components/MachineIdentitiesTable.tsx index 9929d7500..d17786712 100644 --- a/frontend/src/pages/admin/ResourceOverviewPage/components/MachineIdentitiesTable.tsx +++ b/frontend/src/pages/admin/ResourceOverviewPage/components/MachineIdentitiesTable.tsx @@ -185,18 +185,11 @@ export const MachineIdentitiesTable = () => { const handleRemoveServerAdmin = async () => { const { id } = popUp?.removeServerAdmin?.data as { id: string; name: string }; - try { - await deleteIdentitySuperAdminAccess(id); - createNotification({ - type: "success", - text: "Successfully removed server admin permissions" - }); - } catch { - createNotification({ - type: "error", - text: "Error removing server admin permissions" - }); - } + await deleteIdentitySuperAdminAccess(id); + createNotification({ + type: "success", + text: "Successfully removed server admin permissions" + }); handlePopUpClose("removeServerAdmin"); }; diff --git a/frontend/src/pages/admin/ResourceOverviewPage/components/OrganizationsTable.tsx b/frontend/src/pages/admin/ResourceOverviewPage/components/OrganizationsTable.tsx index fbb9462d0..93d0253ff 100644 --- a/frontend/src/pages/admin/ResourceOverviewPage/components/OrganizationsTable.tsx +++ b/frontend/src/pages/admin/ResourceOverviewPage/components/OrganizationsTable.tsx @@ -179,12 +179,6 @@ const ViewMembersModalContent = ({ text: "Successfully resent org invitation", type: "success" }); - } catch (err) { - console.error(err); - createNotification({ - text: "Failed to resend org invitation", - type: "error" - }); } finally { setResendInviteId(null); } @@ -479,26 +473,19 @@ const OrganizationsPanelTable = ({ const { mutateAsync: accessOrganization } = useServerAdminAccessOrg(); const handleAccessOrg = async (orgId: string) => { - try { - await accessOrganization(orgId); + await accessOrganization(orgId); - navigate({ - to: "/login/select-organization", - search: { - org_id: orgId - } - }); + navigate({ + to: "/login/select-organization", + search: { + org_id: orgId + } + }); - createNotification({ - text: "Successfully joined organization", - type: "success" - }); - } catch { - createNotification({ - text: "Failed to join organization", - type: "error" - }); - } + createNotification({ + text: "Successfully joined organization", + type: "success" + }); }; return ( diff --git a/frontend/src/pages/admin/ResourceOverviewPage/components/UserIdentitiesTable.tsx b/frontend/src/pages/admin/ResourceOverviewPage/components/UserIdentitiesTable.tsx index d61d428af..c343a58eb 100644 --- a/frontend/src/pages/admin/ResourceOverviewPage/components/UserIdentitiesTable.tsx +++ b/frontend/src/pages/admin/ResourceOverviewPage/components/UserIdentitiesTable.tsx @@ -364,18 +364,11 @@ export const UserIdentitiesTable = () => { const handleRemoveUser = async () => { const { id } = popUp?.removeUser?.data as { id: string; username: string }; - try { - await deleteUser(id); - createNotification({ - type: "success", - text: "Successfully deleted user" - }); - } catch { - createNotification({ - type: "error", - text: "Error deleting user" - }); - } + await deleteUser(id); + createNotification({ + type: "success", + text: "Successfully deleted user" + }); handlePopUpClose("removeUser"); }; @@ -383,18 +376,11 @@ export const UserIdentitiesTable = () => { const handleGrantServerAdminAccess = async () => { const { id } = popUp?.upgradeToServerAdmin?.data as { id: string; username: string }; - try { - await grantAdminAccess(id); - createNotification({ - type: "success", - text: "Successfully granted server admin access to user" - }); - } catch { - createNotification({ - type: "error", - text: "Error granting server admin access to user" - }); - } + await grantAdminAccess(id); + createNotification({ + type: "success", + text: "Successfully granted server admin access to user" + }); handlePopUpClose("upgradeToServerAdmin"); }; @@ -402,39 +388,25 @@ export const UserIdentitiesTable = () => { const handleRemoveServerAdminAccess = async () => { const { id } = popUp?.removeServerAdmin?.data as { id: string; username: string }; - try { - await removeAdminAccess(id); - createNotification({ - type: "success", - text: "Successfully removed server admin access from user" - }); - } catch { - createNotification({ - type: "error", - text: "Error removing server admin access from user" - }); - } + await removeAdminAccess(id); + createNotification({ + type: "success", + text: "Successfully removed server admin access from user" + }); handlePopUpClose("removeServerAdmin"); }; const handleRemoveUsers = async () => { - try { - await deleteUsers(selectedUsers.map((user) => user.id)); + await deleteUsers(selectedUsers.map((user) => user.id)); - createNotification({ - text: "Successfully removed users", - type: "success" - }); + createNotification({ + text: "Successfully removed users", + type: "success" + }); - setSelectedUsers([]); - handlePopUpClose("removeUsers"); - } catch { - createNotification({ - text: "Failed to remove users", - type: "error" - }); - } + setSelectedUsers([]); + handlePopUpClose("removeUsers"); }; return ( diff --git a/frontend/src/pages/admin/SignUpPage/SignUpPage.tsx b/frontend/src/pages/admin/SignUpPage/SignUpPage.tsx index 04bd2f55c..81959a647 100644 --- a/frontend/src/pages/admin/SignUpPage/SignUpPage.tsx +++ b/frontend/src/pages/admin/SignUpPage/SignUpPage.tsx @@ -6,7 +6,6 @@ import { useNavigate } from "@tanstack/react-router"; import { AnimatePresence, motion } from "framer-motion"; import { z } from "zod"; -import { createNotification } from "@app/components/notifications"; // TODO(akhilmhdh): rewrite this into module functions in lib import SecurityClient from "@app/components/utilities/SecurityClient"; import { Button, ContentLoader, FormControl, Input } from "@app/components/v2"; @@ -46,29 +45,21 @@ export const SignUpPage = () => { const handleFormSubmit = async ({ email, password, firstName, lastName }: TFormSchema) => { // avoid multi submission if (isSubmitting) return; - try { - const res = await createAdminUser({ - email, - password, - firstName, - lastName - }); + const res = await createAdminUser({ + email, + password, + firstName, + lastName + }); - SecurityClient.setToken(res.token); - await selectOrganization({ organizationId: res.organization.id }); + SecurityClient.setToken(res.token); + await selectOrganization({ organizationId: res.organization.id }); - // TODO(akhilmhdh): This is such a confusing pattern and too unreliable - // Will be refactored in next iteration to make it url based rather than local storage ones - // Part of migration to nextjs 14 - localStorage.setItem("orgData.id", res.organization.id); - navigate({ to: "/admin" }); - } catch (err) { - console.log(err); - createNotification({ - type: "error", - text: "Failed to create admin" - }); - } + // TODO(akhilmhdh): This is such a confusing pattern and too unreliable + // Will be refactored in next iteration to make it url based rather than local storage ones + // Part of migration to nextjs 14 + localStorage.setItem("orgData.id", res.organization.id); + navigate({ to: "/admin" }); }; if (config?.initialized) return ; diff --git a/frontend/src/pages/auth/PasswordSetupPage/PasswordSetupPage.tsx b/frontend/src/pages/auth/PasswordSetupPage/PasswordSetupPage.tsx index a1dad3cc5..9626f4cc5 100644 --- a/frontend/src/pages/auth/PasswordSetupPage/PasswordSetupPage.tsx +++ b/frontend/src/pages/auth/PasswordSetupPage/PasswordSetupPage.tsx @@ -75,11 +75,7 @@ export const PasswordSetupPage = () => { setTimeout(() => { window.location.href = "/login"; }, 3000); - } catch (error) { - createNotification({ - type: "error", - text: (error as Error).message ?? "Error setting password" - }); + } catch { navigate({ to: "/personal-settings" }); } } diff --git a/frontend/src/pages/auth/SignUpSsoPage/components/EmailConfirmationStep/EmailConfirmationStep.tsx b/frontend/src/pages/auth/SignUpSsoPage/components/EmailConfirmationStep/EmailConfirmationStep.tsx index efa498749..2240fe263 100644 --- a/frontend/src/pages/auth/SignUpSsoPage/components/EmailConfirmationStep/EmailConfirmationStep.tsx +++ b/frontend/src/pages/auth/SignUpSsoPage/components/EmailConfirmationStep/EmailConfirmationStep.tsx @@ -73,67 +73,53 @@ export const EmailConfirmationStep = ({ const { mutateAsync: verifyEmailVerificationCode } = useVerifyEmailVerificationCode(); const checkCode = async () => { - try { - await verifyEmailVerificationCode({ username, code }); - setCodeError(false); + await verifyEmailVerificationCode({ username, code }); + setCodeError(false); - createNotification({ - text: "Successfully verified code", - type: "success" - }); + createNotification({ + text: "Successfully verified code", + type: "success" + }); - switch (authType) { - case UserAliasType.SAML: { - window.open(`/api/v1/sso/redirect/saml2/organizations/${organizationSlug}`); - window.close(); - break; - } - case UserAliasType.LDAP: { - navigate({ to: "/login/ldap", search: { organizationSlug } }); - break; - } - case UserAliasType.OIDC: { - window.open(`/api/v1/sso/oidc/login?orgSlug=${organizationSlug}`); - window.close(); - break; - } - default: { - setStep(1); - break; - } + switch (authType) { + case UserAliasType.SAML: { + window.open(`/api/v1/sso/redirect/saml2/organizations/${organizationSlug}`); + window.close(); + break; + } + case UserAliasType.LDAP: { + navigate({ to: "/login/ldap", search: { organizationSlug } }); + break; + } + case UserAliasType.OIDC: { + window.open(`/api/v1/sso/oidc/login?orgSlug=${organizationSlug}`); + window.close(); + break; + } + default: { + setStep(1); + break; } - } catch { - createNotification({ - text: "Failed to verify code", - type: "error" - }); } setCode(""); }; const resendCode = async () => { - try { - const queryParams = new URLSearchParams(window.location.search); - const token = queryParams.get("token"); - if (!token) { - createNotification({ - text: "Failed to resend code, no token found", - type: "error" - }); - return; - } - await sendEmailVerificationCode(token); + const queryParams = new URLSearchParams(window.location.search); + const token = queryParams.get("token"); + if (!token) { createNotification({ - text: "Successfully resent code", - type: "success" - }); - } catch { - createNotification({ - text: "Failed to resend code", + text: "Failed to resend code, no token found", type: "error" }); + return; } + await sendEmailVerificationCode(token); + createNotification({ + text: "Successfully resent code", + type: "success" + }); }; return ( diff --git a/frontend/src/pages/cert-manager/AlertingPage/components/PkiAlertModal.tsx b/frontend/src/pages/cert-manager/AlertingPage/components/PkiAlertModal.tsx index 5601e48db..af5bcb7ae 100644 --- a/frontend/src/pages/cert-manager/AlertingPage/components/PkiAlertModal.tsx +++ b/frontend/src/pages/cert-manager/AlertingPage/components/PkiAlertModal.tsx @@ -113,52 +113,44 @@ export const PkiAlertModal = ({ popUp, handlePopUpToggle }: Props) => { alertUnit, emails }: FormData) => { - try { - if (!projectId) return; + if (!projectId) return; - const emailArray = emails - .split(",") - .map((email) => email.trim()) - .filter((email) => email.length > 0); + const emailArray = emails + .split(",") + .map((email) => email.trim()) + .filter((email) => email.length > 0); - const alertBeforeDays = convertToDays(alertUnit, Number(alertBefore)); + const alertBeforeDays = convertToDays(alertUnit, Number(alertBefore)); - if (alert) { - // update - await updatePkiAlert({ - alertId: alert.id, - pkiCollectionId, - name, - projectId, - alertBeforeDays, - emails: emailArray - }); - } else { - // create - await createPkiAlert({ - name, - projectId, - pkiCollectionId, - alertBeforeDays, - emails: emailArray - }); - } - - handlePopUpToggle("pkiAlert", false); - - reset(); - - createNotification({ - text: `Successfully ${alert ? "updated" : "created"} alert`, - type: "success" + if (alert) { + // update + await updatePkiAlert({ + alertId: alert.id, + pkiCollectionId, + name, + projectId, + alertBeforeDays, + emails: emailArray }); - } catch (err) { - console.error(err); - createNotification({ - text: `Failed to ${alert ? "updated" : "created"} alert`, - type: "error" + } else { + // create + await createPkiAlert({ + name, + projectId, + pkiCollectionId, + alertBeforeDays, + emails: emailArray }); } + + handlePopUpToggle("pkiAlert", false); + + reset(); + + createNotification({ + text: `Successfully ${alert ? "updated" : "created"} alert`, + type: "success" + }); }; return ( diff --git a/frontend/src/pages/cert-manager/AlertingPage/components/PkiAlertsSection.tsx b/frontend/src/pages/cert-manager/AlertingPage/components/PkiAlertsSection.tsx index 329974f65..1529dfc19 100644 --- a/frontend/src/pages/cert-manager/AlertingPage/components/PkiAlertsSection.tsx +++ b/frontend/src/pages/cert-manager/AlertingPage/components/PkiAlertsSection.tsx @@ -22,27 +22,19 @@ export const PkiAlertsSection = () => { ] as const); const onRemoveAlertSubmit = async (alertId: string) => { - try { - if (!projectId) return; + if (!projectId) return; - await deletePkiAlert({ - alertId, - projectId - }); + await deletePkiAlert({ + alertId, + projectId + }); - createNotification({ - text: "Successfully deleted alert", - type: "success" - }); + createNotification({ + text: "Successfully deleted alert", + type: "success" + }); - handlePopUpClose("deletePkiAlert"); - } catch (err) { - console.error(err); - createNotification({ - text: "Failed to delete alert", - type: "error" - }); - } + handlePopUpClose("deletePkiAlert"); }; return ( diff --git a/frontend/src/pages/cert-manager/AlertingPage/components/PkiCollectionModal.tsx b/frontend/src/pages/cert-manager/AlertingPage/components/PkiCollectionModal.tsx index 5900a1ba9..a29e9028b 100644 --- a/frontend/src/pages/cert-manager/AlertingPage/components/PkiCollectionModal.tsx +++ b/frontend/src/pages/cert-manager/AlertingPage/components/PkiCollectionModal.tsx @@ -62,49 +62,41 @@ export const PkiCollectionModal = ({ popUp, handlePopUpToggle }: Props) => { }, [pkiCollection]); const onFormSubmit = async ({ name, description }: FormData) => { - try { - if (!projectId) return; + if (!projectId) return; - if (pkiCollection) { - // update - await updatePkiCollection({ - collectionId: pkiCollection.id, - name, - description, - projectId - }); - } else { - // create - const { id: collectionId } = await createPkiCollection({ - name, - description, - projectId - }); - - navigate({ - to: "/projects/cert-management/$projectId/pki-collections/$collectionId", - params: { - projectId, - collectionId - } - }); - } - - handlePopUpToggle("pkiCollection", false); - - reset(); - - createNotification({ - text: `Successfully ${pkiCollection ? "updated" : "created"} PKI collection`, - type: "success" + if (pkiCollection) { + // update + await updatePkiCollection({ + collectionId: pkiCollection.id, + name, + description, + projectId }); - } catch (err) { - console.error(err); - createNotification({ - text: `Failed to ${pkiCollection ? "updated" : "created"} PKI collection`, - type: "error" + } else { + // create + const { id: collectionId } = await createPkiCollection({ + name, + description, + projectId + }); + + navigate({ + to: "/projects/cert-management/$projectId/pki-collections/$collectionId", + params: { + projectId, + collectionId + } }); } + + handlePopUpToggle("pkiCollection", false); + + reset(); + + createNotification({ + text: `Successfully ${pkiCollection ? "updated" : "created"} PKI collection`, + type: "success" + }); }; return ( diff --git a/frontend/src/pages/cert-manager/AlertingPage/components/PkiCollectionSection.tsx b/frontend/src/pages/cert-manager/AlertingPage/components/PkiCollectionSection.tsx index eecceaa7d..fa9cf7bea 100644 --- a/frontend/src/pages/cert-manager/AlertingPage/components/PkiCollectionSection.tsx +++ b/frontend/src/pages/cert-manager/AlertingPage/components/PkiCollectionSection.tsx @@ -22,27 +22,19 @@ export const PkiCollectionSection = () => { ] as const); const onRemovePkiCollectionSubmit = async (collectionId: string) => { - try { - if (!projectId) return; + if (!projectId) return; - await deletePkiCollection({ - collectionId, - projectId - }); + await deletePkiCollection({ + collectionId, + projectId + }); - createNotification({ - text: "Successfully deleted PKI collection", - type: "success" - }); + createNotification({ + text: "Successfully deleted PKI collection", + type: "success" + }); - handlePopUpClose("deletePkiCollection"); - } catch (err) { - console.error(err); - createNotification({ - text: "Failed to delete PKI collection", - type: "error" - }); - } + handlePopUpClose("deletePkiCollection"); }; return ( diff --git a/frontend/src/pages/cert-manager/CertAuthDetailsByIDPage/CertAuthDetailsByIDPage.tsx b/frontend/src/pages/cert-manager/CertAuthDetailsByIDPage/CertAuthDetailsByIDPage.tsx index ca73abd50..b464a2230 100644 --- a/frontend/src/pages/cert-manager/CertAuthDetailsByIDPage/CertAuthDetailsByIDPage.tsx +++ b/frontend/src/pages/cert-manager/CertAuthDetailsByIDPage/CertAuthDetailsByIDPage.tsx @@ -57,33 +57,26 @@ const Page = () => { ] as const); const onRemoveCaSubmit = async () => { - try { - if (!currentProject?.slug) return; + if (!currentProject?.slug) return; - await deleteCa({ - caName, - projectId: currentProject.id, - type: CaType.INTERNAL - }); + await deleteCa({ + caName, + projectId: currentProject.id, + type: CaType.INTERNAL + }); - createNotification({ - text: "Successfully deleted CA", - type: "success" - }); + createNotification({ + text: "Successfully deleted CA", + type: "success" + }); - handlePopUpClose("deleteCa"); - navigate({ - to: "/projects/cert-management/$projectId/certificate-authorities", - params: { - projectId - } - }); - } catch { - createNotification({ - text: "Failed to delete CA", - type: "error" - }); - } + handlePopUpClose("deleteCa"); + navigate({ + to: "/projects/cert-management/$projectId/certificate-authorities", + params: { + projectId + } + }); }; return ( diff --git a/frontend/src/pages/cert-manager/CertAuthDetailsByIDPage/components/CaRenewalModal.tsx b/frontend/src/pages/cert-manager/CertAuthDetailsByIDPage/components/CaRenewalModal.tsx index 857586a58..c6283da37 100644 --- a/frontend/src/pages/cert-manager/CertAuthDetailsByIDPage/components/CaRenewalModal.tsx +++ b/frontend/src/pages/cert-manager/CertAuthDetailsByIDPage/components/CaRenewalModal.tsx @@ -84,27 +84,23 @@ export const CaRenewalModal = ({ popUp, handlePopUpToggle }: Props) => { // }, [ca, parentCa]); const onFormSubmit = async ({ type, notAfter }: FormData) => { - try { - if (!projectSlug || !popUpData.caId) return; + if (!projectSlug || !popUpData.caId) return; - await renewCa({ - projectSlug, - caId: popUpData.caId, - notAfter, - type - }); + await renewCa({ + projectSlug, + caId: popUpData.caId, + notAfter, + type + }); - handlePopUpToggle("renewCa", false); + handlePopUpToggle("renewCa", false); - createNotification({ - text: "Successfully renewed CA", - type: "success" - }); + createNotification({ + text: "Successfully renewed CA", + type: "success" + }); - reset(); - } catch (err) { - console.error(err); - } + reset(); }; return ( diff --git a/frontend/src/pages/cert-manager/CertificateAuthoritiesPage/components/CaInstallCertModal/ExternalCaInstallForm.tsx b/frontend/src/pages/cert-manager/CertificateAuthoritiesPage/components/CaInstallCertModal/ExternalCaInstallForm.tsx index f730322c9..8a7e9690e 100644 --- a/frontend/src/pages/cert-manager/CertificateAuthoritiesPage/components/CaInstallCertModal/ExternalCaInstallForm.tsx +++ b/frontend/src/pages/cert-manager/CertificateAuthoritiesPage/components/CaInstallCertModal/ExternalCaInstallForm.tsx @@ -48,29 +48,22 @@ export const ExternalCaInstallForm = ({ caId, handlePopUpToggle }: Props) => { }, []); const onFormSubmit = async ({ certificate, certificateChain }: FormData) => { - try { - if (!csr || !caId || !currentProject?.slug) return; + if (!csr || !caId || !currentProject?.slug) return; - await importCaCertificate({ - caId, - projectSlug: currentProject?.slug, - certificate, - certificateChain - }); + await importCaCertificate({ + caId, + projectSlug: currentProject?.slug, + certificate, + certificateChain + }); - reset(); + reset(); - createNotification({ - text: "Successfully installed certificate for CA", - type: "success" - }); - handlePopUpToggle("installCaCert", false); - } catch { - createNotification({ - text: "Failed to install certificate for CA", - type: "error" - }); - } + createNotification({ + text: "Successfully installed certificate for CA", + type: "success" + }); + handlePopUpToggle("installCaCert", false); }; const downloadTxtFile = (filename: string, content: string) => { diff --git a/frontend/src/pages/cert-manager/CertificateAuthoritiesPage/components/CaInstallCertModal/InternalCaInstallForm.tsx b/frontend/src/pages/cert-manager/CertificateAuthoritiesPage/components/CaInstallCertModal/InternalCaInstallForm.tsx index 5979d9711..f80e21212 100644 --- a/frontend/src/pages/cert-manager/CertificateAuthoritiesPage/components/CaInstallCertModal/InternalCaInstallForm.tsx +++ b/frontend/src/pages/cert-manager/CertificateAuthoritiesPage/components/CaInstallCertModal/InternalCaInstallForm.tsx @@ -101,37 +101,30 @@ export const InternalCaInstallForm = ({ caId, handlePopUpToggle }: Props) => { }, [parentCa]); const onFormSubmit = async ({ notAfter, maxPathLength }: FormData) => { - try { - if (!csr || !caId || !currentProject?.slug) return; + if (!csr || !caId || !currentProject?.slug) return; - const { certificate, certificateChain } = await signIntermediate({ - caId: parentCaId, - csr, - maxPathLength: Number(maxPathLength), - notAfter, - notBefore: new Date().toISOString() - }); + const { certificate, certificateChain } = await signIntermediate({ + caId: parentCaId, + csr, + maxPathLength: Number(maxPathLength), + notAfter, + notBefore: new Date().toISOString() + }); - await importCaCertificate({ - caId, - projectSlug: currentProject?.slug, - certificate, - certificateChain - }); + await importCaCertificate({ + caId, + projectSlug: currentProject?.slug, + certificate, + certificateChain + }); - reset(); + reset(); - createNotification({ - text: "Successfully installed certificate for CA", - type: "success" - }); - handlePopUpToggle("installCaCert", false); - } catch { - createNotification({ - text: "Failed to install certificate for CA", - type: "error" - }); - } + createNotification({ + text: "Successfully installed certificate for CA", + type: "success" + }); + handlePopUpToggle("installCaCert", false); }; function generatePathLengthOpts(parentCaMaxPathLength: number): number[] { diff --git a/frontend/src/pages/cert-manager/CertificateAuthoritiesPage/components/CaModal.tsx b/frontend/src/pages/cert-manager/CertificateAuthoritiesPage/components/CaModal.tsx index a19a3a9c7..53434b79d 100644 --- a/frontend/src/pages/cert-manager/CertificateAuthoritiesPage/components/CaModal.tsx +++ b/frontend/src/pages/cert-manager/CertificateAuthoritiesPage/components/CaModal.tsx @@ -175,48 +175,40 @@ export const CaModal = ({ popUp, handlePopUpToggle }: Props) => { status, configuration }: FormData) => { - try { - if (!currentProject?.slug) return; + if (!currentProject?.slug) return; - if (ca) { - // update - await updateMutateAsync({ - caName: ca.name, - projectId: currentProject.id, - name, - type: CaType.INTERNAL, - status, - enableDirectIssuance - }); - } else { - // create - await createMutateAsync({ - projectId: currentProject.id, - name, - type, - status, - enableDirectIssuance, - configuration: { - ...configuration, - maxPathLength: Number(configuration.maxPathLength) - } - }); - } - - reset(); - handlePopUpToggle("ca", false); - - createNotification({ - text: `Successfully ${ca ? "updated" : "created"} CA`, - type: "success" + if (ca) { + // update + await updateMutateAsync({ + caName: ca.name, + projectId: currentProject.id, + name, + type: CaType.INTERNAL, + status, + enableDirectIssuance }); - } catch (err) { - console.error(err); - createNotification({ - text: "Failed to create CA", - type: "error" + } else { + // create + await createMutateAsync({ + projectId: currentProject.id, + name, + type, + status, + enableDirectIssuance, + configuration: { + ...configuration, + maxPathLength: Number(configuration.maxPathLength) + } }); } + + reset(); + handlePopUpToggle("ca", false); + + createNotification({ + text: `Successfully ${ca ? "updated" : "created"} CA`, + type: "success" + }); }; return ( diff --git a/frontend/src/pages/cert-manager/CertificateAuthoritiesPage/components/CaSection.tsx b/frontend/src/pages/cert-manager/CertificateAuthoritiesPage/components/CaSection.tsx index 1e264dadc..918a844b1 100644 --- a/frontend/src/pages/cert-manager/CertificateAuthoritiesPage/components/CaSection.tsx +++ b/frontend/src/pages/cert-manager/CertificateAuthoritiesPage/components/CaSection.tsx @@ -27,44 +27,29 @@ export const CaSection = () => { ] as const); const onRemoveCaSubmit = async (caName: string) => { - try { - if (!currentProject?.slug) return; + if (!currentProject?.slug) return; - await deleteCa({ caName, projectId: currentProject.id, type: CaType.INTERNAL }); + await deleteCa({ caName, projectId: currentProject.id, type: CaType.INTERNAL }); - createNotification({ - text: "Successfully deleted CA", - type: "success" - }); + createNotification({ + text: "Successfully deleted CA", + type: "success" + }); - handlePopUpClose("deleteCa"); - } catch { - createNotification({ - text: "Failed to delete CA", - type: "error" - }); - } + handlePopUpClose("deleteCa"); }; const onUpdateCaStatus = async ({ caName, status }: { caName: string; status: CaStatus }) => { - try { - if (!currentProject?.slug) return; + if (!currentProject?.slug) return; - await updateCa({ caName, projectId: currentProject.id, type: CaType.INTERNAL, status }); + await updateCa({ caName, projectId: currentProject.id, type: CaType.INTERNAL, status }); - createNotification({ - text: `Successfully ${status === CaStatus.ACTIVE ? "enabled" : "disabled"} CA`, - type: "success" - }); + createNotification({ + text: `Successfully ${status === CaStatus.ACTIVE ? "enabled" : "disabled"} CA`, + type: "success" + }); - handlePopUpClose("caStatus"); - } catch (err) { - console.error(err); - createNotification({ - text: `Failed to ${status === CaStatus.ACTIVE ? "enabled" : "disabled"} CA`, - type: "error" - }); - } + handlePopUpClose("caStatus"); }; return ( diff --git a/frontend/src/pages/cert-manager/CertificateAuthoritiesPage/components/ExternalCaModal.tsx b/frontend/src/pages/cert-manager/CertificateAuthoritiesPage/components/ExternalCaModal.tsx index a1fdcfc1f..be757e65b 100644 --- a/frontend/src/pages/cert-manager/CertificateAuthoritiesPage/components/ExternalCaModal.tsx +++ b/frontend/src/pages/cert-manager/CertificateAuthoritiesPage/components/ExternalCaModal.tsx @@ -297,63 +297,55 @@ export const ExternalCaModal = ({ popUp, handlePopUpToggle }: Props) => { status, configuration: formConfiguration }: FormData) => { - try { - if (!currentProject?.slug) return; + if (!currentProject?.slug) return; - let configPayload: any; + let configPayload: any; - if (type === CaType.ACME && "dnsAppConnection" in formConfiguration) { - configPayload = { - dnsProviderConfig: formConfiguration.dnsProviderConfig, - directoryUrl: formConfiguration.directoryUrl, - accountEmail: formConfiguration.accountEmail, - dnsAppConnectionId: formConfiguration.dnsAppConnection.id, - eabKid: formConfiguration.eabKid, - eabHmacKey: formConfiguration.eabHmacKey - }; - } else if (type === CaType.AZURE_AD_CS && "azureAdcsConnection" in formConfiguration) { - configPayload = { - azureAdcsConnectionId: formConfiguration.azureAdcsConnection.id - }; - } else { - throw new Error("Invalid certificate authority configuration"); - } + if (type === CaType.ACME && "dnsAppConnection" in formConfiguration) { + configPayload = { + dnsProviderConfig: formConfiguration.dnsProviderConfig, + directoryUrl: formConfiguration.directoryUrl, + accountEmail: formConfiguration.accountEmail, + dnsAppConnectionId: formConfiguration.dnsAppConnection.id, + eabKid: formConfiguration.eabKid, + eabHmacKey: formConfiguration.eabHmacKey + }; + } else if (type === CaType.AZURE_AD_CS && "azureAdcsConnection" in formConfiguration) { + configPayload = { + azureAdcsConnectionId: formConfiguration.azureAdcsConnection.id + }; + } else { + throw new Error("Invalid certificate authority configuration"); + } - if (ca) { - await updateMutateAsync({ - caName: ca.name, - projectId: currentProject.id, - name, - type, - status, - enableDirectIssuance: type === CaType.AZURE_AD_CS ? false : enableDirectIssuance, - configuration: configPayload - }); - } else { - await createMutateAsync({ - projectId: currentProject.id, - name, - type, - status, - enableDirectIssuance: type === CaType.AZURE_AD_CS ? false : enableDirectIssuance, - configuration: configPayload - }); - } - - reset(); - handlePopUpToggle("ca", false); - - createNotification({ - text: `Successfully ${ca ? "updated" : "created"} CA`, - type: "success" + if (ca) { + await updateMutateAsync({ + caName: ca.name, + projectId: currentProject.id, + name, + type, + status, + enableDirectIssuance: type === CaType.AZURE_AD_CS ? false : enableDirectIssuance, + configuration: configPayload }); - } catch (err) { - console.error(err); - createNotification({ - text: "Failed to create CA", - type: "error" + } else { + await createMutateAsync({ + projectId: currentProject.id, + name, + type, + status, + enableDirectIssuance: type === CaType.AZURE_AD_CS ? false : enableDirectIssuance, + configuration: configPayload }); } + + reset(); + handlePopUpToggle("ca", false); + + createNotification({ + text: `Successfully ${ca ? "updated" : "created"} CA`, + type: "success" + }); }; return ( diff --git a/frontend/src/pages/cert-manager/CertificateAuthoritiesPage/components/ExternalCaSection.tsx b/frontend/src/pages/cert-manager/CertificateAuthoritiesPage/components/ExternalCaSection.tsx index 24bfb79ac..31894b855 100644 --- a/frontend/src/pages/cert-manager/CertificateAuthoritiesPage/components/ExternalCaSection.tsx +++ b/frontend/src/pages/cert-manager/CertificateAuthoritiesPage/components/ExternalCaSection.tsx @@ -23,23 +23,16 @@ export const ExternalCaSection = () => { ] as const); const onRemoveCaSubmit = async (caName: string, type: CaType) => { - try { - if (!currentProject?.id) return; + if (!currentProject?.id) return; - await deleteCa({ caName, type, projectId: currentProject.id }); + await deleteCa({ caName, type, projectId: currentProject.id }); - createNotification({ - text: "Successfully deleted CA", - type: "success" - }); + createNotification({ + text: "Successfully deleted CA", + type: "success" + }); - handlePopUpClose("deleteCa"); - } catch { - createNotification({ - text: "Failed to delete CA", - type: "error" - }); - } + handlePopUpClose("deleteCa"); }; const onUpdateCaStatus = async ({ @@ -51,24 +44,16 @@ export const ExternalCaSection = () => { type: CaType; status: CaStatus; }) => { - try { - if (!currentProject?.slug) return; + if (!currentProject?.slug) return; - await updateCa({ caName: name, type, status, projectId: currentProject.id }); + await updateCa({ caName: name, type, status, projectId: currentProject.id }); - createNotification({ - text: `Successfully ${status === CaStatus.ACTIVE ? "enabled" : "disabled"} CA`, - type: "success" - }); + createNotification({ + text: `Successfully ${status === CaStatus.ACTIVE ? "enabled" : "disabled"} CA`, + type: "success" + }); - handlePopUpClose("caStatus"); - } catch (err) { - console.error(err); - createNotification({ - text: `Failed to ${status === CaStatus.ACTIVE ? "enable" : "disable"} CA`, - type: "error" - }); - } + handlePopUpClose("caStatus"); }; return ( diff --git a/frontend/src/pages/cert-manager/CertificatesPage/components/CertificateImportModal.tsx b/frontend/src/pages/cert-manager/CertificatesPage/components/CertificateImportModal.tsx index bb0bbda0b..d0434b79a 100644 --- a/frontend/src/pages/cert-manager/CertificatesPage/components/CertificateImportModal.tsx +++ b/frontend/src/pages/cert-manager/CertificatesPage/components/CertificateImportModal.tsx @@ -71,38 +71,30 @@ export const CertificateImportModal = ({ popUp, handlePopUpToggle }: Props) => { chainPem, collectionId }: FormData) => { - try { - if (!currentProject?.slug) return; + if (!currentProject?.slug) return; - const { serialNumber, certificate, certificateChain, privateKey } = await importCertificate({ - projectSlug: currentProject.slug, + const { serialNumber, certificate, certificateChain, privateKey } = await importCertificate({ + projectSlug: currentProject.slug, - certificatePem, - privateKeyPem, - chainPem, - pkiCollectionId: collectionId - }); + certificatePem, + privateKeyPem, + chainPem, + pkiCollectionId: collectionId + }); - reset(); + reset(); - setCertificateDetails({ - serialNumber, - certificate, - certificateChain, - privateKey - }); + setCertificateDetails({ + serialNumber, + certificate, + certificateChain, + privateKey + }); - createNotification({ - text: "Successfully imported certificate", - type: "success" - }); - } catch (err) { - console.error(err); - createNotification({ - text: "Failed to import certificate", - type: "error" - }); - } + createNotification({ + text: "Successfully imported certificate", + type: "success" + }); }; return ( diff --git a/frontend/src/pages/cert-manager/CertificatesPage/components/CertificateIssuanceModal.tsx b/frontend/src/pages/cert-manager/CertificatesPage/components/CertificateIssuanceModal.tsx index 98ee930d5..81bc5461f 100644 --- a/frontend/src/pages/cert-manager/CertificatesPage/components/CertificateIssuanceModal.tsx +++ b/frontend/src/pages/cert-manager/CertificatesPage/components/CertificateIssuanceModal.tsx @@ -94,9 +94,9 @@ const createSchema = (shouldShowSubjectSection: boolean) => { export type FormData = z.infer>; type Props = { - popUp: UsePopUpState<["certificateIssuance"]>; + popUp: UsePopUpState<["issueCertificate"]>; handlePopUpToggle: ( - popUpName: keyof UsePopUpState<["certificateIssuance"]>, + popUpName: keyof UsePopUpState<["issueCertificate"]>, state?: boolean ) => void; profileId?: string; @@ -115,7 +115,7 @@ export const CertificateIssuanceModal = ({ popUp, handlePopUpToggle, profileId } const { currentProject } = useProject(); const inputSerialNumber = - (popUp?.certificateIssuance?.data as { serialNumber: string })?.serialNumber || ""; + (popUp?.issueCertificate?.data as { serialNumber: string })?.serialNumber || ""; const sanitizedSerialNumber = inputSerialNumber.replace(/[^a-fA-F0-9:]/g, ""); const { data: cert } = useGetCert(sanitizedSerialNumber); @@ -181,7 +181,7 @@ export const CertificateIssuanceModal = ({ popUp, handlePopUpToggle, profileId } } = useCertificateTemplate( templateData, actualSelectedProfile, - popUp?.certificateIssuance?.isOpen || false, + popUp?.issueCertificate?.isOpen || false, setValue, watch ); @@ -227,10 +227,10 @@ export const CertificateIssuanceModal = ({ popUp, handlePopUpToggle, profileId } }, [cert, reset]); useEffect(() => { - if (popUp?.certificateIssuance?.isOpen && profileId && !cert) { + if (popUp?.issueCertificate?.isOpen && profileId && !cert) { setValue("profileId", profileId); } - }, [popUp?.certificateIssuance?.isOpen, profileId, cert, setValue]); + }, [popUp?.issueCertificate?.isOpen, profileId, cert, setValue]); const onFormSubmit = useCallback( async ({ @@ -243,84 +243,72 @@ export const CertificateIssuanceModal = ({ popUp, handlePopUpToggle, profileId } keyUsages, extendedKeyUsages }: FormData) => { - try { - if (!currentProject?.slug) { - createNotification({ - text: "Project not found. Please refresh and try again.", - type: "error" - }); - return; - } - - if (!formProfileId) { - createNotification({ - text: "Please select a certificate profile.", - type: "error" - }); - return; - } - - let commonName = ""; - if ( - constraints.shouldShowSubjectSection && - subjectAttributes && - subjectAttributes.length > 0 - ) { - commonName = getAttributeValue(subjectAttributes, "common_name"); - if (!commonName.trim()) { - createNotification({ - text: "Common name is required.", - type: "error" - }); - return; - } - } - - const certificateRequest: any = { - profileId: formProfileId, - projectSlug: currentProject.slug, - ttl, - signatureAlgorithm, - keyAlgorithm, - keyUsages: filterUsages(keyUsages) as CertKeyUsage[], - extendedKeyUsages: filterUsages(extendedKeyUsages) as CertExtendedKeyUsage[] - }; - - if (constraints.shouldShowSubjectSection && commonName) { - certificateRequest.commonName = commonName; - } - if (constraints.shouldShowSanSection && subjectAltNames && subjectAltNames.length > 0) { - const formattedSans = formatSubjectAltNames(subjectAltNames); - if (formattedSans && formattedSans.length > 0) { - certificateRequest.altNames = formattedSans; - } - } - - const { serialNumber, certificate, certificateChain, privateKey } = - await createCertificate(certificateRequest); - - setCertificateDetails({ - serialNumber, - certificate, - certificateChain, - privateKey - }); - + if (!currentProject?.slug) { createNotification({ - text: "Successfully created certificate", - type: "success" - }); - } catch (err) { - console.error("Certificate creation failed:", err); - const errorMessage = - err instanceof Error - ? err.message - : "An unexpected error occurred while creating the certificate"; - createNotification({ - text: `Failed to create certificate: ${errorMessage}`, + text: "Project not found. Please refresh and try again.", type: "error" }); + return; } + + if (!formProfileId) { + createNotification({ + text: "Please select a certificate profile.", + type: "error" + }); + return; + } + + let commonName = ""; + if ( + constraints.shouldShowSubjectSection && + subjectAttributes && + subjectAttributes.length > 0 + ) { + commonName = getAttributeValue(subjectAttributes, "common_name"); + if (!commonName.trim()) { + createNotification({ + text: "Common name is required.", + type: "error" + }); + return; + } + } + + const certificateRequest: any = { + profileId: formProfileId, + projectSlug: currentProject.slug, + ttl, + signatureAlgorithm, + keyAlgorithm, + keyUsages: filterUsages(keyUsages) as CertKeyUsage[], + extendedKeyUsages: filterUsages(extendedKeyUsages) as CertExtendedKeyUsage[] + }; + + if (constraints.shouldShowSubjectSection && commonName) { + certificateRequest.commonName = commonName; + } + if (constraints.shouldShowSanSection && subjectAltNames && subjectAltNames.length > 0) { + const formattedSans = formatSubjectAltNames(subjectAltNames); + if (formattedSans && formattedSans.length > 0) { + certificateRequest.altNames = formattedSans; + } + } + + const { serialNumber, certificate, certificateChain, privateKey } = + await createCertificate(certificateRequest); + + setCertificateDetails({ + serialNumber, + certificate, + certificateChain, + privateKey + }); + + createNotification({ + text: "Successfully created certificate", + type: "success" + }); }, [ currentProject?.slug, @@ -344,9 +332,9 @@ export const CertificateIssuanceModal = ({ popUp, handlePopUpToggle, profileId } return ( { - handlePopUpToggle("certificateIssuance", isOpen); + handlePopUpToggle("issueCertificate", isOpen); if (!isOpen) { resetAllState(); } @@ -515,7 +503,7 @@ export const CertificateIssuanceModal = ({ popUp, handlePopUpToggle, profileId } colorSchema="secondary" variant="plain" onClick={() => { - handlePopUpToggle("certificateIssuance", false); + handlePopUpToggle("issueCertificate", false); }} > Cancel diff --git a/frontend/src/pages/cert-manager/CertificatesPage/components/CertificateManageRenewalModal.tsx b/frontend/src/pages/cert-manager/CertificatesPage/components/CertificateManageRenewalModal.tsx index d6199678a..96eb2654a 100644 --- a/frontend/src/pages/cert-manager/CertificatesPage/components/CertificateManageRenewalModal.tsx +++ b/frontend/src/pages/cert-manager/CertificatesPage/components/CertificateManageRenewalModal.tsx @@ -163,38 +163,28 @@ export const CertificateManageRenewalModal = ({ popUp, handlePopUpToggle }: Prop }, [popUp.manageRenewal.isOpen, defaultRenewalDays, reset]); const onUpdateRenewal = async (data: FormData) => { - try { - if (!currentProject?.slug) { - createNotification({ - text: "Unable to update auto-renewal: Project not found. Please refresh the page and try again.", - type: "error" - }); - return; - } - - await updateRenewalConfig({ - certificateId: certificateData.certificateId, - renewBeforeDays: data.renewBeforeDays, - projectSlug: currentProject.slug - }); - + if (!currentProject?.slug) { createNotification({ - text: isAutoRenewalEnabled - ? "Auto-renewal configuration updated successfully" - : "Auto-renewal enabled successfully", - type: "success" - }); - - handlePopUpToggle("manageRenewal", false); - } catch (err) { - console.error(err); - createNotification({ - text: isAutoRenewalEnabled - ? "Failed to update auto-renewal configuration. Please check your inputs and try again." - : "Failed to enable auto-renewal. Please check your inputs and try again.", + text: "Unable to update auto-renewal: Project not found. Please refresh the page and try again.", type: "error" }); + return; } + + await updateRenewalConfig({ + certificateId: certificateData.certificateId, + renewBeforeDays: data.renewBeforeDays, + projectSlug: currentProject.slug + }); + + createNotification({ + text: isAutoRenewalEnabled + ? "Auto-renewal configuration updated successfully" + : "Auto-renewal enabled successfully", + type: "success" + }); + + handlePopUpToggle("manageRenewal", false); }; const getModalTitle = () => { diff --git a/frontend/src/pages/cert-manager/CertificatesPage/components/CertificateModal.tsx b/frontend/src/pages/cert-manager/CertificatesPage/components/CertificateModal.tsx index 22718222a..75ae0e848 100644 --- a/frontend/src/pages/cert-manager/CertificatesPage/components/CertificateModal.tsx +++ b/frontend/src/pages/cert-manager/CertificatesPage/components/CertificateModal.tsx @@ -75,6 +75,7 @@ export type FormData = z.infer; type Props = { popUp: UsePopUpState<["certificate"]>; handlePopUpToggle: (popUpName: keyof UsePopUpState<["certificate"]>, state?: boolean) => void; + preselectedTemplate?: { id: string; name: string }; }; type TCertificateDetails = { @@ -86,7 +87,7 @@ type TCertificateDetails = { const CERT_TEMPLATE_NONE_VALUE = "none"; -export const CertificateModal = ({ popUp, handlePopUpToggle }: Props) => { +export const CertificateModal = ({ popUp, handlePopUpToggle, preselectedTemplate }: Props) => { const [certificateDetails, setCertificateDetails] = useState(null); const { currentProject } = useProject(); const { data: cert } = useGetCert( @@ -147,13 +148,15 @@ export const CertificateModal = ({ popUp, handlePopUpToggle }: Props) => { (cert.extendedKeyUsages || []).map((name) => [name, true]) ) }); - } else { + } else if (popUp?.certificate?.isOpen) { + const templateId = preselectedTemplate?.id || CERT_TEMPLATE_NONE_VALUE; + reset({ caId: "", commonName: "", subjectAltNames: "", ttl: "", - certificateTemplateId: CERT_TEMPLATE_NONE_VALUE, + certificateTemplateId: templateId, keyUsages: { [CertKeyUsage.DIGITAL_SIGNATURE]: true, [CertKeyUsage.KEY_ENCIPHERMENT]: true @@ -161,7 +164,7 @@ export const CertificateModal = ({ popUp, handlePopUpToggle }: Props) => { extendedKeyUsages: {} }); } - }, [cert]); + }, [cert, preselectedTemplate, popUp?.certificate?.isOpen]); useEffect(() => { if (!cert && selectedCertTemplate) { @@ -186,45 +189,41 @@ export const CertificateModal = ({ popUp, handlePopUpToggle }: Props) => { keyUsages, extendedKeyUsages }: FormData) => { - try { - if (!currentProject?.slug) return; + if (!currentProject?.slug) return; - const { serialNumber, certificate, certificateChain, privateKey } = await createCertificate({ - caId: !selectedCertTemplate ? caId : undefined, - certificateTemplateId: selectedCertTemplate ? selectedCertTemplateId : undefined, - projectSlug: currentProject.slug, - pkiCollectionId: collectionId, - commonName, - subjectAltNames, - ttl, - keyUsages: Object.entries(keyUsages) - .filter(([, value]) => value) - .map(([key]) => key as CertKeyUsage), - extendedKeyUsages: Object.entries(extendedKeyUsages) - .filter(([, value]) => value) - .map(([key]) => key as CertExtendedKeyUsage) - }); + const { serialNumber, certificate, certificateChain, privateKey } = await createCertificate({ + caId: !selectedCertTemplate ? caId : undefined, + certificateTemplateId: selectedCertTemplate ? selectedCertTemplateId : undefined, + projectSlug: currentProject.slug, + pkiCollectionId: collectionId, + commonName, + subjectAltNames, + ttl, + keyUsages: Object.entries(keyUsages) + .filter(([, value]) => value) + .map(([key]) => + key === CertKeyUsage.CRL_SIGN + ? "cRLSign" + : key.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase()) + ), + extendedKeyUsages: Object.entries(extendedKeyUsages) + .filter(([, value]) => value) + .map(([key]) => key.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase())) + }); - reset(); + reset(); - setCertificateDetails({ - serialNumber, - certificate, - certificateChain, - privateKey - }); + setCertificateDetails({ + serialNumber, + certificate, + certificateChain, + privateKey + }); - createNotification({ - text: "Successfully created certificate", - type: "success" - }); - } catch (err) { - console.error(err); - createNotification({ - text: "Failed to create certificate", - type: "error" - }); - } + createNotification({ + text: "Successfully created certificate", + type: "success" + }); }; useEffect(() => { @@ -277,15 +276,25 @@ export const CertificateModal = ({ popUp, handlePopUpToggle }: Props) => { isRequired > { - if (e === "all") onChange(undefined); - else setValue("userAgentType", e as UserAgentType, { shouldDirty: true }); - }} - className={twMerge("w-full border border-mineshaft-500 bg-mineshaft-700")} - position="popper" - > - - All sources - - {userAgentTypes.map(({ label, value: userAgent }) => ( - - {label} - - ))} - + value === (userAgentType.value as UserAgentType) + ) ?? null + } + isClearable + onChange={(option) => + onChange((option as SingleValue<(typeof userAgentTypes)[number]>)?.value) + } + placeholder="All sources" + options={userAgentTypes} + getOptionValue={(option) => option.value} + getOptionLabel={(option) => option.label} + /> )} /> @@ -289,10 +231,10 @@ export const LogsFilter = ({ presets, setFilter, filter, project }: Props) => { { - resetField("project"); - resetField("environment"); - setValue("secretPath", ""); - setValue("secretKey", ""); + setValue("project", null, { shouldDirty: true }); + setValue("environment", undefined, { shouldDirty: true }); + setValue("secretPath", "", { shouldDirty: true }); + setValue("secretKey", "", { shouldDirty: true }); }} > { } className={twMerge(!selectedProject && "opacity-50")} onClear={() => { - resetField("environment"); + setValue("environment", undefined, { shouldDirty: true }); }} > { } className={twMerge(!selectedProject && "opacity-50")} onClear={() => { - setValue("secretPath", ""); + setValue("secretPath", "", { shouldDirty: true }); }} > { className={twMerge(!selectedProject && "opacity-50")} label="Secret Key" onClear={() => { - setValue("secretKey", ""); + setValue("secretKey", "", { shouldDirty: true }); }} > { }, [data]); const onFormSubmit = async ({ name }: { name: string }) => { - try { - if (!currentOrg?.id) return; - if (name === "") return; - await mutateAsync({ - name, - organizationId: currentOrg.id - }); + if (!currentOrg?.id) return; + if (name === "") return; + await mutateAsync({ + name, + organizationId: currentOrg.id + }); - createNotification({ - text: "Successfully updated business name", - type: "success" - }); - } catch (err) { - console.error(err); - createNotification({ - text: "Failed to update business name", - type: "error" - }); - } + createNotification({ + text: "Successfully updated business name", + type: "success" + }); }; return ( diff --git a/frontend/src/pages/organization/BillingPage/components/BillingDetailsTab/InvoiceEmailSection.tsx b/frontend/src/pages/organization/BillingPage/components/BillingDetailsTab/InvoiceEmailSection.tsx index 8b471346f..dc05a7208 100644 --- a/frontend/src/pages/organization/BillingPage/components/BillingDetailsTab/InvoiceEmailSection.tsx +++ b/frontend/src/pages/organization/BillingPage/components/BillingDetailsTab/InvoiceEmailSection.tsx @@ -35,26 +35,18 @@ export const InvoiceEmailSection = () => { }, [data]); const onFormSubmit = async ({ email }: { email: string }) => { - try { - if (!currentOrg?.id) return; - if (email === "") return; + if (!currentOrg?.id) return; + if (email === "") return; - await mutateAsync({ - email, - organizationId: currentOrg.id - }); + await mutateAsync({ + email, + organizationId: currentOrg.id + }); - createNotification({ - text: "Successfully updated invoice email recipient", - type: "success" - }); - } catch (err) { - console.error(err); - createNotification({ - text: "Failed to update invoice email recipient", - type: "error" - }); - } + createNotification({ + text: "Successfully updated invoice email recipient", + type: "success" + }); }; return ( diff --git a/frontend/src/pages/organization/BillingPage/components/BillingDetailsTab/PmtMethodsTable.tsx b/frontend/src/pages/organization/BillingPage/components/BillingDetailsTab/PmtMethodsTable.tsx index bf0851e11..15a6bc8e9 100644 --- a/frontend/src/pages/organization/BillingPage/components/BillingDetailsTab/PmtMethodsTable.tsx +++ b/frontend/src/pages/organization/BillingPage/components/BillingDetailsTab/PmtMethodsTable.tsx @@ -39,22 +39,15 @@ export const PmtMethodsTable = () => { }); return; } - try { - await deleteOrgPmtMethod.mutateAsync({ - organizationId: currentOrg.id, - pmtMethodId: pmtMethodToRemove.id - }); - createNotification({ - type: "success", - text: "Successfully removed payment method" - }); - handlePopUpClose("removeCard"); - } catch (error: any) { - createNotification({ - type: "error", - text: error.message ?? "Error removing payment method" - }); - } + await deleteOrgPmtMethod.mutateAsync({ + organizationId: currentOrg.id, + pmtMethodId: pmtMethodToRemove.id + }); + createNotification({ + type: "success", + text: "Successfully removed payment method" + }); + handlePopUpClose("removeCard"); }; return ( diff --git a/frontend/src/pages/organization/BillingPage/components/BillingDetailsTab/TaxIDModal.tsx b/frontend/src/pages/organization/BillingPage/components/BillingDetailsTab/TaxIDModal.tsx index 01b11e81a..23542ac8d 100644 --- a/frontend/src/pages/organization/BillingPage/components/BillingDetailsTab/TaxIDModal.tsx +++ b/frontend/src/pages/organization/BillingPage/components/BillingDetailsTab/TaxIDModal.tsx @@ -98,26 +98,18 @@ export const TaxIDModal = ({ popUp, handlePopUpClose, handlePopUpToggle }: Props }); const onTaxIDModalSubmit = async ({ type, value }: AddTaxIDFormData) => { - try { - if (!currentOrg?.id) return; - await addOrgTaxId.mutateAsync({ - organizationId: currentOrg.id, - type, - value - }); + if (!currentOrg?.id) return; + await addOrgTaxId.mutateAsync({ + organizationId: currentOrg.id, + type, + value + }); - createNotification({ - text: "Successfully added Tax ID", - type: "success" - }); - handlePopUpClose("addTaxID"); - } catch (err) { - console.error(err); - createNotification({ - text: "Failed to add Tax ID", - type: "error" - }); - } + createNotification({ + text: "Successfully added Tax ID", + type: "success" + }); + handlePopUpClose("addTaxID"); }; return ( diff --git a/frontend/src/pages/organization/GroupDetailsByIDPage/GroupDetailsByIDPage.tsx b/frontend/src/pages/organization/GroupDetailsByIDPage/GroupDetailsByIDPage.tsx index 33acbc418..e6d3736fb 100644 --- a/frontend/src/pages/organization/GroupDetailsByIDPage/GroupDetailsByIDPage.tsx +++ b/frontend/src/pages/organization/GroupDetailsByIDPage/GroupDetailsByIDPage.tsx @@ -54,27 +54,19 @@ const Page = () => { ] as const); const onDeleteGroupSubmit = async ({ name, id }: { name: string; id: string }) => { - try { - await deleteMutateAsync({ - id - }); - createNotification({ - text: `Successfully deleted the ${name} group`, - type: "success" - }); - navigate({ - to: "/organization/access-management" as const, - search: { - selectedTab: TabSections.Groups - } - }); - } catch (err) { - console.error(err); - createNotification({ - text: `Failed to delete the ${name} group`, - type: "error" - }); - } + await deleteMutateAsync({ + id + }); + createNotification({ + text: `Successfully deleted the ${name} group`, + type: "success" + }); + navigate({ + to: "/organization/access-management" as const, + search: { + selectedTab: TabSections.Groups + } + }); handlePopUpClose("deleteGroup"); }; diff --git a/frontend/src/pages/organization/GroupDetailsByIDPage/components/AddGroupMemberModal.tsx b/frontend/src/pages/organization/GroupDetailsByIDPage/components/AddGroupMemberModal.tsx index 0995830e5..b9d1b184c 100644 --- a/frontend/src/pages/organization/GroupDetailsByIDPage/components/AddGroupMemberModal.tsx +++ b/frontend/src/pages/organization/GroupDetailsByIDPage/components/AddGroupMemberModal.tsx @@ -63,31 +63,24 @@ export const AddGroupMembersModal = ({ popUp, handlePopUpToggle }: Props) => { const { mutateAsync: addUserToGroupMutateAsync } = useAddUserToGroup(); const handleAddMember = async (username: string) => { - try { - if (!popUpData?.slug) { - createNotification({ - text: "Some data is missing, please refresh the page and try again", - type: "error" - }); - return; - } - - await addUserToGroupMutateAsync({ - groupId: popUpData.groupId, - username, - slug: popUpData.slug - }); - + if (!popUpData?.slug) { createNotification({ - text: "Successfully assigned user to the group", - type: "success" - }); - } catch { - createNotification({ - text: "Failed to assign user to the group", + text: "Some data is missing, please refresh the page and try again", type: "error" }); + return; } + + await addUserToGroupMutateAsync({ + groupId: popUpData.groupId, + username, + slug: popUpData.slug + }); + + createNotification({ + text: "Successfully assigned user to the group", + type: "success" + }); }; return ( diff --git a/frontend/src/pages/organization/GroupDetailsByIDPage/components/GroupCreateUpdateModal.tsx b/frontend/src/pages/organization/GroupDetailsByIDPage/components/GroupCreateUpdateModal.tsx index e4364e874..bc6e3fab5 100644 --- a/frontend/src/pages/organization/GroupDetailsByIDPage/components/GroupCreateUpdateModal.tsx +++ b/frontend/src/pages/organization/GroupDetailsByIDPage/components/GroupCreateUpdateModal.tsx @@ -77,43 +77,36 @@ export const GroupCreateUpdateModal = ({ popUp, handlePopUpClose, handlePopUpTog }, [popUp?.groupCreateUpdate?.data, roles]); const onGroupModalSubmit = async ({ name, slug, role }: TGroupFormData) => { - try { - if (!currentOrg?.id) return; + if (!currentOrg?.id) return; - const group = popUp?.groupCreateUpdate?.data as { - groupId: string; - name: string; - slug: string; - }; + const group = popUp?.groupCreateUpdate?.data as { + groupId: string; + name: string; + slug: string; + }; - if (group) { - await updateMutateAsync({ - id: group.groupId, - name, - slug, - role: role.slug || undefined - }); - } else { - await createMutateAsync({ - name, - slug, - organizationId: currentOrg.id, - role: role.slug || undefined - }); - } - handlePopUpToggle("groupCreateUpdate", false); - reset(); - - createNotification({ - text: `Successfully ${popUp?.groupCreateUpdate?.data ? "updated" : "created"} group`, - type: "success" + if (group) { + await updateMutateAsync({ + id: group.groupId, + name, + slug, + role: role.slug || undefined }); - } catch { - createNotification({ - text: `Failed to ${popUp?.groupCreateUpdate?.data ? "updated" : "created"} group`, - type: "error" + } else { + await createMutateAsync({ + name, + slug, + organizationId: currentOrg.id, + role: role.slug || undefined }); } + handlePopUpToggle("groupCreateUpdate", false); + reset(); + + createNotification({ + text: `Successfully ${popUp?.groupCreateUpdate?.data ? "updated" : "created"} group`, + type: "success" + }); }; return ( diff --git a/frontend/src/pages/organization/GroupDetailsByIDPage/components/GroupMembersSection/GroupMembersSection.tsx b/frontend/src/pages/organization/GroupDetailsByIDPage/components/GroupMembersSection/GroupMembersSection.tsx index 2ca6859b0..c78b5404e 100644 --- a/frontend/src/pages/organization/GroupDetailsByIDPage/components/GroupMembersSection/GroupMembersSection.tsx +++ b/frontend/src/pages/organization/GroupDetailsByIDPage/components/GroupMembersSection/GroupMembersSection.tsx @@ -29,25 +29,18 @@ export const GroupMembersSection = ({ groupId, groupSlug }: Props) => { const { mutateAsync: removeUserFromGroupMutateAsync } = useRemoveUserFromGroup(); const handleRemoveUserFromGroup = async (username: string) => { - try { - await removeUserFromGroupMutateAsync({ - groupId, - username, - slug: groupSlug - }); + await removeUserFromGroupMutateAsync({ + groupId, + username, + slug: groupSlug + }); - createNotification({ - text: `Successfully removed user ${username} from the group`, - type: "success" - }); + createNotification({ + text: `Successfully removed user ${username} from the group`, + type: "success" + }); - handlePopUpToggle("removeMemberFromGroup", false); - } catch { - createNotification({ - text: `Failed to remove user ${username} from the group`, - type: "error" - }); - } + handlePopUpToggle("removeMemberFromGroup", false); }; return ( diff --git a/frontend/src/pages/organization/IdentityDetailsByIDPage/IdentityDetailsByIDPage.tsx b/frontend/src/pages/organization/IdentityDetailsByIDPage/IdentityDetailsByIDPage.tsx index 797e740ee..33753da39 100644 --- a/frontend/src/pages/organization/IdentityDetailsByIDPage/IdentityDetailsByIDPage.tsx +++ b/frontend/src/pages/organization/IdentityDetailsByIDPage/IdentityDetailsByIDPage.tsx @@ -44,34 +44,23 @@ const Page = () => { ] as const); const onDeleteIdentitySubmit = async (id: string) => { - try { - await deleteIdentity({ - identityId: id, - organizationId: orgId - }); + await deleteIdentity({ + identityId: id, + organizationId: orgId + }); - createNotification({ - text: "Successfully deleted identity", - type: "success" - }); + createNotification({ + text: "Successfully deleted identity", + type: "success" + }); - handlePopUpClose("deleteIdentity"); - navigate({ - to: "/organization/access-management", - search: { - selectedTab: OrgAccessControlTabSections.Identities - } - }); - } catch (err) { - console.error(err); - const error = err as any; - const text = error?.response?.data?.message ?? "Failed to delete identity"; - - createNotification({ - text, - type: "error" - }); - } + handlePopUpClose("deleteIdentity"); + navigate({ + to: "/organization/access-management", + search: { + selectedTab: OrgAccessControlTabSections.Identities + } + }); }; return ( diff --git a/frontend/src/pages/organization/IdentityDetailsByIDPage/components/IdentityProjectsSection/IdentityAddToProjectModal.tsx b/frontend/src/pages/organization/IdentityDetailsByIDPage/components/IdentityProjectsSection/IdentityAddToProjectModal.tsx index 2e5c7101c..2f407142a 100644 --- a/frontend/src/pages/organization/IdentityDetailsByIDPage/components/IdentityProjectsSection/IdentityAddToProjectModal.tsx +++ b/frontend/src/pages/organization/IdentityDetailsByIDPage/components/IdentityProjectsSection/IdentityAddToProjectModal.tsx @@ -75,30 +75,19 @@ const Content = ({ identityId, handlePopUpToggle }: Omit) => { }, [workspaces, projectMemberships]); const onFormSubmit = async ({ project: selectedProject, role }: FormData) => { - try { - await addIdentityToWorkspace({ - projectId: selectedProject.id, - identityId, - role: role.slug || undefined - }); + await addIdentityToWorkspace({ + projectId: selectedProject.id, + identityId, + role: role.slug || undefined + }); - createNotification({ - text: "Successfully added identity to project", - type: "success" - }); + createNotification({ + text: "Successfully added identity to project", + type: "success" + }); - reset(); - handlePopUpToggle("addIdentityToProject", false); - } catch (err) { - console.error(err); - const error = err as any; - const text = error?.response?.data?.message ?? "Failed to add identity to project"; - - createNotification({ - text, - type: "error" - }); - } + reset(); + handlePopUpToggle("addIdentityToProject", false); }; const isProjectSelected = Boolean(projectId); diff --git a/frontend/src/pages/organization/IdentityDetailsByIDPage/components/IdentityProjectsSection/IdentityProjectsSection.tsx b/frontend/src/pages/organization/IdentityDetailsByIDPage/components/IdentityProjectsSection/IdentityProjectsSection.tsx index 6530b9ae5..8d67ef6a4 100644 --- a/frontend/src/pages/organization/IdentityDetailsByIDPage/components/IdentityProjectsSection/IdentityProjectsSection.tsx +++ b/frontend/src/pages/organization/IdentityDetailsByIDPage/components/IdentityProjectsSection/IdentityProjectsSection.tsx @@ -22,28 +22,17 @@ export const IdentityProjectsSection = ({ identityId }: Props) => { ] as const); const onRemoveIdentitySubmit = async (id: string, projectId: string) => { - try { - await deleteMutateAsync({ - identityId: id, - projectId - }); + await deleteMutateAsync({ + identityId: id, + projectId + }); - createNotification({ - text: "Successfully removed identity from project", - type: "success" - }); + createNotification({ + text: "Successfully removed identity from project", + type: "success" + }); - handlePopUpClose("removeIdentityFromProject"); - } catch (err) { - console.error(err); - const error = err as any; - const text = error?.response?.data?.message ?? "Failed to remove identity from project"; - - createNotification({ - text, - type: "error" - }); - } + handlePopUpClose("removeIdentityFromProject"); }; return ( diff --git a/frontend/src/pages/organization/IdentityDetailsByIDPage/components/IdentityTokenModal.tsx b/frontend/src/pages/organization/IdentityDetailsByIDPage/components/IdentityTokenModal.tsx index d2b865a5a..d5c1aa2ac 100644 --- a/frontend/src/pages/organization/IdentityDetailsByIDPage/components/IdentityTokenModal.tsx +++ b/frontend/src/pages/organization/IdentityDetailsByIDPage/components/IdentityTokenModal.tsx @@ -72,46 +72,33 @@ export const IdentityTokenModal = ({ popUp, handlePopUpToggle }: Props) => { }, [popUp?.token?.data]); const onFormSubmit = async ({ name }: FormData) => { - try { - if (tokenData?.tokenId) { - // update + if (tokenData?.tokenId) { + // update - await updateToken({ - identityId: tokenData.identityId, - tokenId: tokenData.tokenId, - name - }); - - handlePopUpToggle("token", false); - } else { - // create - - const newTokenData = await createToken({ - identityId: tokenData.identityId, - name - }); - - setToken(newTokenData.accessToken); - } - - createNotification({ - text: `Successfully ${popUp?.token?.data ? "updated" : "created"} token`, - type: "success" + await updateToken({ + identityId: tokenData.identityId, + tokenId: tokenData.tokenId, + name }); - reset(); - } catch (err) { - console.error(err); - const error = err as any; - const text = - error?.response?.data?.message ?? - `Failed to ${popUp?.token?.data ? "update" : "create"} token`; + handlePopUpToggle("token", false); + } else { + // create - createNotification({ - text, - type: "error" + const newTokenData = await createToken({ + identityId: tokenData.identityId, + name }); + + setToken(newTokenData.accessToken); } + + createNotification({ + text: `Successfully ${popUp?.token?.data ? "updated" : "created"} token`, + type: "success" + }); + + reset(); }; return ( diff --git a/frontend/src/pages/organization/IdentityDetailsByIDPage/components/ViewIdentityAuthModal/IdentityAuthLockoutFields.tsx b/frontend/src/pages/organization/IdentityDetailsByIDPage/components/ViewIdentityAuthModal/IdentityAuthLockoutFields.tsx index b5cb2d901..4ec5871a2 100644 --- a/frontend/src/pages/organization/IdentityDetailsByIDPage/components/ViewIdentityAuthModal/IdentityAuthLockoutFields.tsx +++ b/frontend/src/pages/organization/IdentityDetailsByIDPage/components/ViewIdentityAuthModal/IdentityAuthLockoutFields.tsx @@ -31,23 +31,15 @@ export const LockoutFields = ({ const [lockedOutState, setLockedOutState] = useState(lockedOut); - async function clearLockouts() { - try { - const deleted = await mutateAsync({ identityId }); - createNotification({ - text: `Successfully cleared ${deleted} lockout${deleted === 1 ? "" : "s"}`, - type: "success" - }); - setLockedOutState(false); - onResetAllLockouts(); - } catch (error) { - console.error(error); - createNotification({ - text: "Failed to clear lockouts. Please try again.", - type: "error" - }); - } - } + const clearLockouts = async () => { + const deleted = await mutateAsync({ identityId }); + createNotification({ + text: `Successfully cleared ${deleted} lockout${deleted === 1 ? "" : "s"}`, + type: "success" + }); + setLockedOutState(false); + onResetAllLockouts(); + }; return ( <> diff --git a/frontend/src/pages/organization/IdentityDetailsByIDPage/components/ViewIdentityAuthModal/IdentityTokenAuthTokensTable.tsx b/frontend/src/pages/organization/IdentityDetailsByIDPage/components/ViewIdentityAuthModal/IdentityTokenAuthTokensTable.tsx index be9c166b3..cc11d9d10 100644 --- a/frontend/src/pages/organization/IdentityDetailsByIDPage/components/ViewIdentityAuthModal/IdentityTokenAuthTokensTable.tsx +++ b/frontend/src/pages/organization/IdentityDetailsByIDPage/components/ViewIdentityAuthModal/IdentityTokenAuthTokensTable.tsx @@ -51,28 +51,17 @@ export const IdentityTokenAuthTokensTable = ({ tokens, identityId }: Props) => { tokenId: string; name: string; }) => { - try { - await revokeToken({ - identityId: parentIdentityId, - tokenId - }); + await revokeToken({ + identityId: parentIdentityId, + tokenId + }); - handlePopUpClose("revokeToken"); + handlePopUpClose("revokeToken"); - createNotification({ - text: `Successfully revoked token ${name ?? ""}`, - type: "success" - }); - } catch (err) { - console.error(err); - const error = err as any; - const text = error?.response?.data?.message ?? "Failed to revoke token"; - - createNotification({ - text, - type: "error" - }); - } + createNotification({ + text: `Successfully revoked token ${name ?? ""}`, + type: "success" + }); }; return ( diff --git a/frontend/src/pages/organization/IdentityDetailsByIDPage/components/ViewIdentityAuthModal/IdentityUniversalAuthClientSecretsTable.tsx b/frontend/src/pages/organization/IdentityDetailsByIDPage/components/ViewIdentityAuthModal/IdentityUniversalAuthClientSecretsTable.tsx index b034b5367..017f30719 100644 --- a/frontend/src/pages/organization/IdentityDetailsByIDPage/components/ViewIdentityAuthModal/IdentityUniversalAuthClientSecretsTable.tsx +++ b/frontend/src/pages/organization/IdentityDetailsByIDPage/components/ViewIdentityAuthModal/IdentityUniversalAuthClientSecretsTable.tsx @@ -43,25 +43,17 @@ export const IdentityUniversalAuthClientSecretsTable = ({ clientSecrets, identit const { mutateAsync: revokeClientSecret } = useRevokeIdentityUniversalAuthClientSecret(); const onDeleteClientSecretSubmit = async (clientSecretId: string) => { - try { - await revokeClientSecret({ - identityId, - clientSecretId - }); + await revokeClientSecret({ + identityId, + clientSecretId + }); - handlePopUpToggle("revokeClientSecret", false); + handlePopUpToggle("revokeClientSecret", false); - createNotification({ - text: "Successfully deleted client secret", - type: "success" - }); - } catch (err) { - console.error(err); - createNotification({ - text: "Failed to delete client secret", - type: "error" - }); - } + createNotification({ + text: "Successfully deleted client secret", + type: "success" + }); }; return ( diff --git a/frontend/src/pages/organization/IdentityDetailsByIDPage/components/ViewIdentityAuthModal/ViewIdentityAuthModal.tsx b/frontend/src/pages/organization/IdentityDetailsByIDPage/components/ViewIdentityAuthModal/ViewIdentityAuthModal.tsx index d49b44f46..be5ae2cc9 100644 --- a/frontend/src/pages/organization/IdentityDetailsByIDPage/components/ViewIdentityAuthModal/ViewIdentityAuthModal.tsx +++ b/frontend/src/pages/organization/IdentityDetailsByIDPage/components/ViewIdentityAuthModal/ViewIdentityAuthModal.tsx @@ -140,25 +140,17 @@ export const Content = ({ } const handleDeleteAuthMethod = async () => { - try { - await revokeMethod({ - identityId, - organizationId: orgId - }); + await revokeMethod({ + identityId, + organizationId: orgId + }); - createNotification({ - text: "Successfully removed auth method", - type: "success" - }); - - handlePopUpToggle("revokeAuthMethod", false); - onDeleteAuthMethod(); - } catch { - createNotification({ - text: "Failed to remove auth method", - type: "error" - }); - } + createNotification({ + text: "Successfully removed auth method", + type: "success" + }); + handlePopUpToggle("revokeAuthMethod", false); + onDeleteAuthMethod(); }; return ( diff --git a/frontend/src/pages/organization/NetworkingPage/components/GatewayTab/components/GatewayCliDeploymentMethod.tsx b/frontend/src/pages/organization/NetworkingPage/components/GatewayTab/components/GatewayCliDeploymentMethod.tsx index 7537d95a3..ae44cdd1e 100644 --- a/frontend/src/pages/organization/NetworkingPage/components/GatewayTab/components/GatewayCliDeploymentMethod.tsx +++ b/frontend/src/pages/organization/NetworkingPage/components/GatewayTab/components/GatewayCliDeploymentMethod.tsx @@ -36,7 +36,6 @@ import { RelayOption } from "./RelayOption"; const baseFormSchema = z.object({ name: slugSchema({ field: "name" }), - instanceDomain: z.string().url("Must be a valid URL").or(z.literal("")), relay: z .object( { @@ -78,7 +77,6 @@ export const GatewayCliDeploymentMethod = () => { const [autogenerateToken, setAutogenerateToken] = useState(true); const [step, setStep] = useState<"form" | "command">("form"); const [name, setName] = useState(""); - const [instanceDomain, setInstanceDomain] = useState(siteURL); const [relay, setRelay] = useState { const validation = formSchemaWithIdentity.safeParse({ name, relay, - identity, - instanceDomain + identity }); if (!validation.success) { setFormErrors(validation.error.issues); @@ -168,20 +165,14 @@ export const GatewayCliDeploymentMethod = () => { type: "info" }); setStep("command"); - } catch (err) { - console.error(err); - createNotification({ - text: "Failed to generate token for the selected identity", - type: "error" - }); + } catch { setIdentityToken(""); } } else { const validation = formSchemaWithToken.safeParse({ name, relay, - identityToken, - instanceDomain + identityToken }); if (!validation.success) { setFormErrors(validation.error.issues); @@ -192,11 +183,10 @@ export const GatewayCliDeploymentMethod = () => { }; const command = useMemo(() => { - const domainFlag = instanceDomain ? ` --domain=${instanceDomain}` : ""; return `infisical gateway start --name=${name} --relay=${ relay?.name || "" - }${domainFlag} --token=${identityToken}`; - }, [name, relay, identityToken, instanceDomain]); + } --domain=${siteURL} --token=${identityToken}`; + }, [name, relay, identityToken, siteURL]); if (step === "command") { return ( @@ -279,19 +269,6 @@ export const GatewayCliDeploymentMethod = () => { /> {errors.relay &&

{errors.relay}

} - - setInstanceDomain(e.target.value)} - placeholder="https://app.infisical.com" - isError={Boolean(errors.instanceDomain)} - /> - {errors.instanceDomain &&

{errors.instanceDomain}

} - {canCreateToken && autogenerateToken ? ( <> { const [name, setName] = useState(""); const [host, setHost] = useState(""); - const [instanceDomain, setInstanceDomain] = useState(siteURL); const [identity, setIdentity] = useState { setFormErrors([]); if (canCreateToken && autogenerateToken) { - const validation = formSchemaWithIdentity.safeParse({ name, host, instanceDomain, identity }); + const validation = formSchemaWithIdentity.safeParse({ name, host, identity }); if (!validation.success) { setFormErrors(validation.error.issues); return; @@ -141,19 +139,13 @@ export const RelayCliDeploymentMethod = () => { type: "info" }); setStep("command"); - } catch (err) { - console.error(err); - createNotification({ - text: "Failed to generate token for the selected identity", - type: "error" - }); + } catch { setIdentityToken(""); } } else { const validation = formSchemaWithToken.safeParse({ name, host, - instanceDomain, identityToken }); if (!validation.success) { @@ -174,9 +166,8 @@ export const RelayCliDeploymentMethod = () => { }; const command = useMemo(() => { - const domainFlag = instanceDomain ? ` --domain=${instanceDomain}` : ""; - return `infisical relay start --name=${name}${domainFlag} --host=${host} --token=${identityToken}`; - }, [name, instanceDomain, host, identityToken]); + return `infisical relay start --name=${name} --domain=${siteURL} --host=${host} --token=${identityToken}`; + }, [name, siteURL, host, identityToken]); if (step === "command") { return ( @@ -244,19 +235,6 @@ export const RelayCliDeploymentMethod = () => { /> {errors.host &&

{errors.host}

} - - setInstanceDomain(e.target.value)} - placeholder="https://app.infisical.com" - isError={Boolean(errors.instanceDomain)} - /> - {errors.instanceDomain &&

{errors.instanceDomain}

} - {canCreateToken && autogenerateToken ? ( <> val !== null, { message: "Identity is required" }) +}); + +const formSchemaWithToken = baseFormSchema.extend({ + identityToken: z.string().min(1, "Token is required") +}); + +const ec2FormSchema = z.object({ + awsRegion: z.string().min(1, "AWS Region is required"), + vpcId: z.string().min(1, "VPC ID is required"), + ami: z.string().min(1, "AMI ID is required"), + subnetId: z.string().min(1, "Subnet ID is required") +}); + +export const RelayTerraformDeploymentMethod = () => { + const { protocol, hostname, port } = window.location; + const portSuffix = port && port !== "80" ? `:${port}` : ""; + const siteURL = `${protocol}//${hostname}${portSuffix}`; + + const [selectedTabIndex, setSelectedTabIndex] = useState(0); + + const [autogenerateToken, setAutogenerateToken] = useState(true); + const [step, setStep] = useState<"form" | "command">("form"); + const [name, setName] = useState(""); + + const [identity, setIdentity] = useState(null); + const [identityToken, setIdentityToken] = useState(""); + const [formErrors, setFormErrors] = useState([]); + + const [awsRegion, setAwsRegion] = useState("us-east-1"); + const [vpcId, setVpcId] = useState(""); + const [ami, setAmi] = useState("ami-01b2110eef525172b"); + const [subnetId, setSubnetId] = useState(""); + + const errors = useMemo(() => { + const errorMap: Record = {}; + formErrors.forEach((issue) => { + if (issue.path.length > 0) { + errorMap[String(issue.path[0])] = issue.message; + } + }); + return errorMap; + }, [formErrors]); + + const { currentOrg } = useOrganization(); + const organizationId = currentOrg?.id || ""; + + const { permission } = useOrgPermission(); + const canCreateToken = permission.can( + OrgPermissionIdentityActions.CreateToken, + OrgPermissionSubjects.Identity + ); + + const { data: identityMembershipOrgsData, isPending: isIdentitiesLoading } = + useGetIdentityMembershipOrgs({ + organizationId, + limit: 20000 + }); + const identityMembershipOrgs = identityMembershipOrgsData?.identityMemberships || []; + + const { mutateAsync: createToken, isPending: isCreatingToken } = + useCreateTokenIdentityTokenAuth(); + const { mutateAsync: addIdentityTokenAuth, isPending: isAddingTokenAuth } = + useAddIdentityTokenAuth(); + const { refetch } = useGetIdentityTokenAuth(identity?.id ?? ""); + + const handleGenerateCommand = async () => { + setFormErrors([]); + + if (canCreateToken && autogenerateToken) { + const validation = formSchemaWithIdentity.safeParse({ name, identity }); + if (!validation.success) { + setFormErrors(validation.error.issues); + return; + } + + if (selectedTabIndex === 0) { + const ec2Validation = ec2FormSchema.safeParse({ awsRegion, vpcId, ami, subnetId }); + if (!ec2Validation.success) { + setFormErrors(ec2Validation.error.issues); + return; + } + } + + const validatedIdentity = validation.data.identity; + + try { + const { data: identityTokenAuth } = await refetch(); + if (!identityTokenAuth) { + await addIdentityTokenAuth({ + identityId: validatedIdentity.id, + organizationId, + accessTokenTTL: 2592000, + accessTokenMaxTTL: 2592000, + accessTokenNumUsesLimit: 0, + accessTokenTrustedIps: [{ ipAddress: "0.0.0.0/0" }, { ipAddress: "::/0" }] + }); + createNotification({ + text: "Token authentication has been automatically enabled for the selected identity. By default, it is configured to allow all IP addresses with a default token TTL of 30 days. You can manage these settings in Access Control.", + type: "warning" + }); + } + + const token = await createToken({ + identityId: validatedIdentity.id, + name: `relay token for ${name} (autogenerated)` + }); + setIdentityToken(token.accessToken); + createNotification({ + text: "Automatically generated a token for the selected identity.", + type: "info" + }); + setStep("command"); + } catch (err) { + console.error(err); + createNotification({ + text: "Failed to generate token for the selected identity", + type: "error" + }); + setIdentityToken(""); + } + } else { + const validation = formSchemaWithToken.safeParse({ + name, + identityToken + }); + if (!validation.success) { + setFormErrors(validation.error.issues); + return; + } + + if (selectedTabIndex === 0) { + const ec2Validation = ec2FormSchema.safeParse({ awsRegion, vpcId, ami, subnetId }); + if (!ec2Validation.success) { + setFormErrors(ec2Validation.error.issues); + return; + } + } + setStep("command"); + } + }; + + const handleIdentityChange = ( + selectedIdentity: SingleValue<{ + id: string; + name: string; + }> + ) => { + setIdentity(selectedIdentity); + }; + + const terraformCommand = useMemo(() => { + return `terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 5.0" + } + } +} + +provider "aws" { + region = "${awsRegion}" +} + +# Security Group for the Infisical Relay instance +resource "aws_security_group" "infisical_relay_sg" { + name = "${name}-relay-sg" + description = "Allows inbound traffic for Infisical Relay and SSH" + vpc_id = "${vpcId}" + + # Inbound: Allows the Infisical platform to securely communicate with the Relay server. + ingress { + from_port = 8443 + to_port = 8443 + protocol = "tcp" + cidr_blocks = ["0.0.0.0/0"] + } + + # Inbound: Allows Infisical Gateway to securely communicate via the Relay. + ingress { + from_port = 2222 + to_port = 2222 + protocol = "tcp" + cidr_blocks = ["0.0.0.0/0"] + } + + # Inbound: Allows secure shell (SSH) access for administration. + ingress { + from_port = 22 + to_port = 22 + protocol = "tcp" + cidr_blocks = ["0.0.0.0/0"] # Restrict this to your IP in production + } + + # Outbound: Allows the Relay server to make necessary outbound connections to the Infisical platform. + egress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } + + tags = { + Name = "${name}-relay-sg" + } +} + +# Elastic IP for a static public IP address +resource "aws_eip" "infisical_relay_eip" { + tags = { + Name = "${name}-relay-eip" + } +} + +# EC2 instance to run Infisical Relay +module "infisical_relay_instance" { + source = "terraform-aws-modules/ec2-instance/aws" + version = "~> 5.6" + + name = "${name}-relay-instance" + ami = "${ami}" + instance_type = "t3.micro" + subnet_id = "${subnetId}" + + vpc_security_group_ids = [aws_security_group.infisical_relay_sg.id] + associate_public_ip_address = false # We are using an Elastic IP instead + + user_data = <<-EOT + #!/bin/bash + set -e + # Install Infisical CLI + curl -1sLf 'https://artifacts-cli.infisical.com/setup.deb.sh' | bash + apt-get update && apt-get install -y infisical + + # Install the relay as a systemd service. + # This example uses a Machine Identity token for authentication via the INFISICAL_TOKEN environment variable. + # + # Note: For production environments, you might consider fetching the token from AWS Parameter Store or AWS Secrets Manager. + export INFISICAL_TOKEN="${identityToken}" + sudo -E infisical relay systemd install \\ + --name "${name}" \\ + --domain "${siteURL}" \\ + --host "\${aws_eip.infisical_relay_eip.public_ip}" + + # Start and enable the service to run on boot + sudo systemctl start infisical-relay + sudo systemctl enable infisical-relay + EOT +} + +# Associate the Elastic IP with the EC2 instance +resource "aws_eip_association" "eip_assoc" { + instance_id = module.infisical_relay_instance.id + allocation_id = aws_eip.infisical_relay_eip.id +} +`; + }, [name, siteURL, identityToken, awsRegion, vpcId, ami, subnetId]); + + if (step === "command") { + return ( + <> +
+ Terraform Configuration + { + navigator.clipboard.writeText(terraformCommand); + createNotification({ + text: "Terraform configuration copied to clipboard", + type: "info" + }); + }} + className="w-10" + > + + +
+
+
+            {terraformCommand}
+          
+
+
+ + + +
+ + ); + } + + return ( + <> + + setName(e.target.value)} + placeholder="Enter relay name..." + isError={Boolean(errors.name)} + /> + {errors.name &&

{errors.name}

} + + {canCreateToken && autogenerateToken ? ( + <> + + + handleIdentityChange( + e as SingleValue<{ + id: string; + name: string; + }> + ) + } + isLoading={isIdentitiesLoading} + placeholder="Select identity..." + options={identityMembershipOrgs.map((membership) => membership.identity)} + getOptionValue={(option) => option.id} + getOptionLabel={(option) => option.name} + /> + {errors.identity &&

{errors.identity}

} + + ) : ( + <> + + setIdentityToken(e.target.value)} + placeholder="Enter identity token..." + isError={Boolean(errors.identityToken)} + /> + {errors.identityToken &&

{errors.identityToken}

} + + )} + + {canCreateToken && ( +
+ { + setAutogenerateToken(Boolean(e)); + }} + id="autogenerate-token" + className="mr-2" + > +
+ Automatically enable token auth and generate a token for identity + + Token authentication will be automatically enabled for the selected identity if + it isn't already configured. By default, it will be configured to allow all + IP addresses with a token TTL of 30 days. You can manage these settings in + Access Control. +
+
A token will automatically be generated to be used with the CLI command. + + } + > + +
+
+
+
+ )} + + + + + `-mb-[0.14rem] px-4 py-2 text-sm font-medium whitespace-nowrap outline-hidden disabled:opacity-60 ${ + selected ? "border-b-2 border-mineshaft-300 text-mineshaft-200" : "text-bunker-300" + }` + } + > + EC2 + + + + + + r.slug === awsRegion)} + onChange={(selected) => { + if (selected) { + setAwsRegion((selected as SingleValue<{ slug: string; name: string }>)!.slug); + } + }} + options={AWS_REGIONS} + getOptionLabel={(option) => option.name} + getOptionValue={(option) => option.slug} + /> + {errors.awsRegion &&

{errors.awsRegion}

} + + setVpcId(e.target.value)} + placeholder="vpc-..." + isError={Boolean(errors.vpcId)} + /> + {errors.vpcId &&

{errors.vpcId}

} + + setAmi(e.target.value)} + placeholder="ami-..." + isError={Boolean(errors.ami)} + /> + {errors.ami &&

{errors.ami}

} + + setSubnetId(e.target.value)} + placeholder="subnet-..." + isError={Boolean(errors.subnetId)} + /> + {errors.subnetId &&

{errors.subnetId}

} +
+
+
+ +
+ + + + +
+ + ); +}; diff --git a/frontend/src/pages/organization/ProjectsPage/components/AllProjectView.tsx b/frontend/src/pages/organization/ProjectsPage/components/AllProjectView.tsx index cf60ffa59..a1bd8c9e4 100644 --- a/frontend/src/pages/organization/ProjectsPage/components/AllProjectView.tsx +++ b/frontend/src/pages/organization/ProjectsPage/components/AllProjectView.tsx @@ -13,7 +13,6 @@ import { useNavigate } from "@tanstack/react-router"; import { CheckIcon } from "lucide-react"; import { twMerge } from "tailwind-merge"; -import { createNotification } from "@app/components/notifications"; import { OrgPermissionCan } from "@app/components/permissions"; import { RequestProjectAccessModal } from "@app/components/projects/RequestProjectAccessModal"; import { @@ -103,22 +102,15 @@ export const AllProjectView = ({ projectId: string, environments: ProjectEnv[] ) => { - try { - await orgAdminAccessProject.mutateAsync({ + await orgAdminAccessProject.mutateAsync({ + projectId + }); + await navigate({ + to: getProjectHomePage(type, environments), + params: { projectId - }); - await navigate({ - to: getProjectHomePage(type, environments), - params: { - projectId - } - }); - } catch { - createNotification({ - text: "Failed to access project", - type: "error" - }); - } + } + }); }; useResetPageHelper({ diff --git a/frontend/src/pages/organization/ProjectsPage/components/MyProjectView.tsx b/frontend/src/pages/organization/ProjectsPage/components/MyProjectView.tsx index a86023b6c..32301923b 100644 --- a/frontend/src/pages/organization/ProjectsPage/components/MyProjectView.tsx +++ b/frontend/src/pages/organization/ProjectsPage/components/MyProjectView.tsx @@ -15,7 +15,6 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { useNavigate } from "@tanstack/react-router"; import { twMerge } from "tailwind-merge"; -import { createNotification } from "@app/components/notifications"; import { OrgPermissionCan } from "@app/components/permissions"; import { Button, @@ -158,32 +157,18 @@ export const MyProjectView = ({ }; const addProjectToFavorites = async (projectId: string) => { - try { - if (currentOrg?.id) { - await updateUserProjectFavorites({ - orgId: currentOrg?.id, - projectFavorites: [...(projectFavorites || []), projectId] - }); - } - } catch { - createNotification({ - text: "Failed to add project to favorites.", - type: "error" + if (currentOrg?.id) { + await updateUserProjectFavorites({ + orgId: currentOrg?.id, + projectFavorites: [...(projectFavorites || []), projectId] }); } }; const removeProjectFromFavorites = async (projectId: string) => { - try { - if (currentOrg?.id) { - await updateUserProjectFavorites({ - orgId: currentOrg?.id, - projectFavorites: [...(projectFavorites || []).filter((entry) => entry !== projectId)] - }); - } - } catch { - createNotification({ - text: "Failed to remove project from favorites.", - type: "error" + if (currentOrg?.id) { + await updateUserProjectFavorites({ + orgId: currentOrg?.id, + projectFavorites: [...(projectFavorites || []).filter((entry) => entry !== projectId)] }); } }; diff --git a/frontend/src/pages/organization/RoleByIDPage/RoleByIDPage.tsx b/frontend/src/pages/organization/RoleByIDPage/RoleByIDPage.tsx index 0d30dd2f8..78c5393a7 100644 --- a/frontend/src/pages/organization/RoleByIDPage/RoleByIDPage.tsx +++ b/frontend/src/pages/organization/RoleByIDPage/RoleByIDPage.tsx @@ -42,36 +42,25 @@ export const Page = () => { ] as const); const onDeleteOrgRoleSubmit = async () => { - try { - if (!orgId || !roleId) return; + if (!orgId || !roleId) return; - await deleteOrgRole({ - orgId, - id: roleId - }); + await deleteOrgRole({ + orgId, + id: roleId + }); - createNotification({ - text: "Successfully deleted organization role", - type: "success" - }); + createNotification({ + text: "Successfully deleted organization role", + type: "success" + }); - handlePopUpClose("deleteOrgRole"); - navigate({ - to: "/organization/access-management" as const, - search: { - selectedTab: OrgAccessControlTabSections.Roles - } - }); - } catch (err) { - console.error(err); - const error = err as any; - const text = error?.response?.data?.message ?? "Failed to delete organization role"; - - createNotification({ - text, - type: "error" - }); - } + handlePopUpClose("deleteOrgRole"); + navigate({ + to: "/organization/access-management" as const, + search: { + selectedTab: OrgAccessControlTabSections.Roles + } + }); }; const isCustomRole = !["admin", "member", "no-access"].includes(data?.slug ?? ""); diff --git a/frontend/src/pages/organization/RoleByIDPage/components/RoleModal.tsx b/frontend/src/pages/organization/RoleByIDPage/components/RoleModal.tsx index 88f568c4a..73da4f161 100644 --- a/frontend/src/pages/organization/RoleByIDPage/components/RoleModal.tsx +++ b/frontend/src/pages/organization/RoleByIDPage/components/RoleModal.tsx @@ -70,55 +70,46 @@ export const RoleModal = ({ popUp, handlePopUpToggle }: Props) => { }, [role]); const onFormSubmit = async ({ name, description, slug }: FormData) => { - try { - if (!orgId) return; + if (!orgId) return; - if (role) { - // update + if (role) { + // update - await updateOrgRole({ - orgId, - id: role.id, - name, - description, - slug - }); - - handlePopUpToggle("role", false); - } else { - // create - - const newRole = await createOrgRole({ - orgId, - name, - description, - slug, - permissions: [] - }); - - handlePopUpToggle("role", false); - navigate({ - to: "/organization/roles/$roleId", - params: { - roleId: newRole.id - } - }); - } - - createNotification({ - text: `Successfully ${popUp?.role?.data ? "updated" : "created"} role`, - type: "success" + await updateOrgRole({ + orgId, + id: role.id, + name, + description, + slug }); - reset(); - } catch { - const text = `Failed to ${popUp?.role?.data ? "update" : "create"} role`; + handlePopUpToggle("role", false); + } else { + // create - createNotification({ - text, - type: "error" + const newRole = await createOrgRole({ + orgId, + name, + description, + slug, + permissions: [] + }); + + handlePopUpToggle("role", false); + navigate({ + to: "/organization/roles/$roleId", + params: { + roleId: newRole.id + } }); } + + createNotification({ + text: `Successfully ${popUp?.role?.data ? "updated" : "created"} role`, + type: "success" + }); + + reset(); }; return ( diff --git a/frontend/src/pages/organization/RoleByIDPage/components/RolePermissionsSection/RolePermissionsSection.tsx b/frontend/src/pages/organization/RoleByIDPage/components/RolePermissionsSection/RolePermissionsSection.tsx index 0d6b269a8..c25d11cb7 100644 --- a/frontend/src/pages/organization/RoleByIDPage/components/RolePermissionsSection/RolePermissionsSection.tsx +++ b/frontend/src/pages/organization/RoleByIDPage/components/RolePermissionsSection/RolePermissionsSection.tsx @@ -107,18 +107,13 @@ export const RolePermissionsSection = ({ roleId }: Props) => { const { mutateAsync: updateRole } = useUpdateOrgRole(); const onSubmit = async (el: TFormSchema) => { - try { - await updateRole({ - orgId, - id: roleId, - ...el, - permissions: formRolePermission2API(el.permissions) - }); - createNotification({ type: "success", text: "Successfully updated role" }); - } catch (err) { - console.log(err); - createNotification({ type: "error", text: "Failed to update role" }); - } + await updateRole({ + orgId, + id: roleId, + ...el, + permissions: formRolePermission2API(el.permissions) + }); + createNotification({ type: "success", text: "Successfully updated role" }); }; const isCustomRole = !["admin", "member", "no-access"].includes(role?.slug ?? ""); diff --git a/frontend/src/pages/organization/SecretSharingPage/components/RequestSecret/RequestSecretForm.tsx b/frontend/src/pages/organization/SecretSharingPage/components/RequestSecret/RequestSecretForm.tsx index 50a9e0f58..d50873339 100644 --- a/frontend/src/pages/organization/SecretSharingPage/components/RequestSecret/RequestSecretForm.tsx +++ b/frontend/src/pages/organization/SecretSharingPage/components/RequestSecret/RequestSecretForm.tsx @@ -56,35 +56,27 @@ export const RequestSecretForm = () => { const onFormSubmit = async ({ name, accessType, expiresIn }: FormData) => { const expiresAt = new Date(new Date().getTime() + Number(expiresIn)); - try { - const { id } = await createSecretRequest({ - name, - accessType, - expiresAt - }); + const { id } = await createSecretRequest({ + name, + accessType, + expiresAt + }); - const link = new URL(`${window.location.origin}/secret-request/secret/${id}`); - if (subOrganization) { - link.searchParams.set("subOrganization", subOrganization); - } - - setSecretLink(link.toString()); - reset(); - - navigator.clipboard.writeText(link.toString()); - setCopyTextSecret("secret"); - - createNotification({ - text: "Shared secret link copied to clipboard.", - type: "success" - }); - } catch (error) { - console.error(error); - createNotification({ - text: "Failed to create a shared secret.", - type: "error" - }); + const link = new URL(`${window.location.origin}/secret-request/secret/${id}`); + if (subOrganization) { + link.searchParams.set("subOrganization", subOrganization); } + + setSecretLink(link.toString()); + reset(); + + navigator.clipboard.writeText(link.toString()); + setCopyTextSecret("secret"); + + createNotification({ + text: "Shared secret link copied to clipboard.", + type: "success" + }); }; const hasSecretLink = Boolean(secretLink); diff --git a/frontend/src/pages/organization/SecretSharingPage/components/RequestSecret/RequestSecretTab.tsx b/frontend/src/pages/organization/SecretSharingPage/components/RequestSecret/RequestSecretTab.tsx index fd3b1d5b5..1253cdbc0 100644 --- a/frontend/src/pages/organization/SecretSharingPage/components/RequestSecret/RequestSecretTab.tsx +++ b/frontend/src/pages/organization/SecretSharingPage/components/RequestSecret/RequestSecretTab.tsx @@ -22,23 +22,15 @@ export const RequestSecretTab = () => { const { mutateAsync: deleteSecretRequest } = useDeleteSecretRequest(); const onDeleteApproved = async () => { - try { - await deleteSecretRequest({ - secretRequestId: popUp.deleteSecretRequestConfirmation.data?.id - }); - createNotification({ - text: "Successfully deleted secret request", - type: "success" - }); + await deleteSecretRequest({ + secretRequestId: popUp.deleteSecretRequestConfirmation.data?.id + }); + createNotification({ + text: "Successfully deleted secret request", + type: "success" + }); - handlePopUpClose("deleteSecretRequestConfirmation"); - } catch (err) { - console.error(err); - createNotification({ - text: "Failed to delete shared secret", - type: "error" - }); - } + handlePopUpClose("deleteSecretRequestConfirmation"); }; return ( diff --git a/frontend/src/pages/organization/SecretSharingPage/components/SecretSharingSettings/OrgSecretShareLimitSection.tsx b/frontend/src/pages/organization/SecretSharingPage/components/SecretSharingSettings/OrgSecretShareLimitSection.tsx index 034c7d8fe..d7c337332 100644 --- a/frontend/src/pages/organization/SecretSharingPage/components/SecretSharingSettings/OrgSecretShareLimitSection.tsx +++ b/frontend/src/pages/organization/SecretSharingPage/components/SecretSharingSettings/OrgSecretShareLimitSection.tsx @@ -90,28 +90,21 @@ export const OrgSecretShareLimitSection = () => { }, [currentOrg, reset]); const handleFormSubmit = async (formData: TForm) => { - try { - const maxSharedSecretLifetimeSeconds = - ms(`${formData.maxLifetimeValue}${formData.maxLifetimeUnit}`) / 1000; + const maxSharedSecretLifetimeSeconds = + ms(`${formData.maxLifetimeValue}${formData.maxLifetimeUnit}`) / 1000; - await mutateAsync({ - orgId: currentOrg.id, - maxSharedSecretViewLimit: formData.shouldLimitView ? Number(formData.maxViewLimit) : null, - maxSharedSecretLifetime: maxSharedSecretLifetimeSeconds - }); + await mutateAsync({ + orgId: currentOrg.id, + maxSharedSecretViewLimit: formData.shouldLimitView ? Number(formData.maxViewLimit) : null, + maxSharedSecretLifetime: maxSharedSecretLifetimeSeconds + }); - createNotification({ - text: "Successfully updated secret share limits", - type: "success" - }); + createNotification({ + text: "Successfully updated secret share limits", + type: "success" + }); - reset(formData); - } catch { - createNotification({ - text: "Failed to update secret share limits", - type: "error" - }); - } + reset(formData); }; // Units for the dropdown with readable labels diff --git a/frontend/src/pages/organization/SecretSharingPage/components/SecretSharingSettings/SecretSharingAllowShareToAnyone.tsx b/frontend/src/pages/organization/SecretSharingPage/components/SecretSharingSettings/SecretSharingAllowShareToAnyone.tsx index 1ea62c187..31b2221ce 100644 --- a/frontend/src/pages/organization/SecretSharingPage/components/SecretSharingSettings/SecretSharingAllowShareToAnyone.tsx +++ b/frontend/src/pages/organization/SecretSharingPage/components/SecretSharingSettings/SecretSharingAllowShareToAnyone.tsx @@ -9,25 +9,17 @@ export const SecretSharingAllowShareToAnyone = () => { const { mutateAsync } = useUpdateOrg(); const handleSecretSharingToggle = async (value: boolean) => { - try { - if (!currentOrg?.id) return; + if (!currentOrg?.id) return; - await mutateAsync({ - orgId: currentOrg.id, - allowSecretSharingOutsideOrganization: value - }); + await mutateAsync({ + orgId: currentOrg.id, + allowSecretSharingOutsideOrganization: value + }); - createNotification({ - text: `Successfully ${value ? "enabled" : "disabled"} secret sharing to members outside of this organization`, - type: "success" - }); - } catch (err) { - console.error(err); - createNotification({ - text: (err as { response: { data: { message: string } } }).response.data.message, - type: "error" - }); - } + createNotification({ + text: `Successfully ${value ? "enabled" : "disabled"} secret sharing to members outside of this organization`, + type: "success" + }); }; return ( diff --git a/frontend/src/pages/organization/SecretSharingPage/components/ShareSecret/ShareSecretTab.tsx b/frontend/src/pages/organization/SecretSharingPage/components/ShareSecret/ShareSecretTab.tsx index d4f2f0a1f..2ea61ca98 100644 --- a/frontend/src/pages/organization/SecretSharingPage/components/ShareSecret/ShareSecretTab.tsx +++ b/frontend/src/pages/organization/SecretSharingPage/components/ShareSecret/ShareSecretTab.tsx @@ -20,23 +20,15 @@ export const ShareSecretTab = () => { const deleteSecretShare = useDeleteSharedSecret(); const onDeleteApproved = async () => { - try { - deleteSecretShare.mutateAsync({ - sharedSecretId: (popUp?.deleteSharedSecretConfirmation?.data as DeleteModalData)?.id - }); - createNotification({ - text: "Successfully deleted shared secret", - type: "success" - }); + deleteSecretShare.mutateAsync({ + sharedSecretId: (popUp?.deleteSharedSecretConfirmation?.data as DeleteModalData)?.id + }); + createNotification({ + text: "Successfully deleted shared secret", + type: "success" + }); - handlePopUpClose("deleteSharedSecretConfirmation"); - } catch (err) { - console.error(err); - createNotification({ - text: "Failed to delete shared secret", - type: "error" - }); - } + handlePopUpClose("deleteSharedSecretConfirmation"); }; return ( diff --git a/frontend/src/pages/organization/SettingsPage/OauthCallbackPage/OauthCallbackPage.tsx b/frontend/src/pages/organization/SettingsPage/OauthCallbackPage/OauthCallbackPage.tsx index df5bf4f60..5efec93d9 100644 --- a/frontend/src/pages/organization/SettingsPage/OauthCallbackPage/OauthCallbackPage.tsx +++ b/frontend/src/pages/organization/SettingsPage/OauthCallbackPage/OauthCallbackPage.tsx @@ -72,20 +72,12 @@ export const OAuthCallbackPage = () => { if (!isReady) return; (async () => { - try { - await handleMicrosoftTeams(); + await handleMicrosoftTeams(); - createNotification({ - text: "Successfully created Microsoft Teams workflow integration", - type: "success" - }); - } catch (err) { - console.error(err); - createNotification({ - text: "Failed to create Microsoft Teams workflow integration", - type: "error" - }); - } + createNotification({ + text: "Successfully created Microsoft Teams workflow integration", + type: "success" + }); })(); }, [isReady]); diff --git a/frontend/src/pages/organization/SettingsPage/components/AuditLogStreamTab/AuditLogStreamForm/AuditLogStreamForm.tsx b/frontend/src/pages/organization/SettingsPage/components/AuditLogStreamTab/AuditLogStreamForm/AuditLogStreamForm.tsx index f59ae23aa..5ea16050a 100644 --- a/frontend/src/pages/organization/SettingsPage/components/AuditLogStreamTab/AuditLogStreamForm/AuditLogStreamForm.tsx +++ b/frontend/src/pages/organization/SettingsPage/components/AuditLogStreamTab/AuditLogStreamForm/AuditLogStreamForm.tsx @@ -28,21 +28,12 @@ const CreateForm = ({ provider, onComplete }: CreateFormProps) => { const onSubmit = async ( formData: DiscriminativePick ) => { - try { - const logStream = await createAuditLogStream.mutateAsync(formData); - createNotification({ - text: `Successfully created ${providerName} Log Stream`, - type: "success" - }); - onComplete(logStream); - } catch (err: any) { - console.error(err); - createNotification({ - title: `Failed to create ${providerName} Log Stream`, - text: err.message, - type: "error" - }); - } + const logStream = await createAuditLogStream.mutateAsync(formData); + createNotification({ + text: `Successfully created ${providerName} Log Stream`, + type: "success" + }); + onComplete(logStream); }; switch (provider) { @@ -68,24 +59,15 @@ const UpdateForm = ({ auditLogStream, onComplete }: UpdateFormProps) => { const onSubmit = async ( formData: DiscriminativePick ) => { - try { - const connection = await updateAuditLogStream.mutateAsync({ - auditLogStreamId: auditLogStream.id, - ...formData - }); - createNotification({ - text: `Successfully updated ${providerName} Log Stream`, - type: "success" - }); - onComplete(connection); - } catch (err: any) { - console.error(err); - createNotification({ - title: `Failed to update ${providerName} Log Stream`, - text: err.message, - type: "error" - }); - } + const connection = await updateAuditLogStream.mutateAsync({ + auditLogStreamId: auditLogStream.id, + ...formData + }); + createNotification({ + text: `Successfully updated ${providerName} Log Stream`, + type: "success" + }); + onComplete(connection); }; switch (auditLogStream.provider) { diff --git a/frontend/src/pages/organization/SettingsPage/components/AuditLogStreamTab/components/DeleteAuditLogStreamModal.tsx b/frontend/src/pages/organization/SettingsPage/components/AuditLogStreamTab/components/DeleteAuditLogStreamModal.tsx index 1a65e6c67..74eb19af3 100644 --- a/frontend/src/pages/organization/SettingsPage/components/AuditLogStreamTab/components/DeleteAuditLogStreamModal.tsx +++ b/frontend/src/pages/organization/SettingsPage/components/AuditLogStreamTab/components/DeleteAuditLogStreamModal.tsx @@ -20,26 +20,17 @@ export const DeleteAuditLogStreamModal = ({ isOpen, onOpenChange, auditLogStream const providerDetails = AUDIT_LOG_STREAM_PROVIDER_MAP[provider]; const handleDelete = async () => { - try { - await deleteAuditLogStream.mutateAsync({ - auditLogStreamId, - provider - }); + await deleteAuditLogStream.mutateAsync({ + auditLogStreamId, + provider + }); - createNotification({ - text: `Successfully deleted ${providerDetails.name} stream`, - type: "success" - }); + createNotification({ + text: `Successfully deleted ${providerDetails.name} stream`, + type: "success" + }); - onOpenChange(false); - } catch (err) { - console.error(err); - - createNotification({ - text: `Failed to delete ${providerDetails.name} stream`, - type: "error" - }); - } + onOpenChange(false); }; return ( diff --git a/frontend/src/pages/organization/SettingsPage/components/ExternalMigrationsTab/components/VaultConnectionSection.tsx b/frontend/src/pages/organization/SettingsPage/components/ExternalMigrationsTab/components/VaultConnectionSection.tsx index c91e9c24c..e802e250b 100644 --- a/frontend/src/pages/organization/SettingsPage/components/ExternalMigrationsTab/components/VaultConnectionSection.tsx +++ b/frontend/src/pages/organization/SettingsPage/components/ExternalMigrationsTab/components/VaultConnectionSection.tsx @@ -54,21 +54,13 @@ export const VaultConnectionSection = () => { const handleDeleteConfirm = async () => { if (!configToDelete) return; - try { - await deleteConfig({ id: configToDelete.id }); - createNotification({ - type: "success", - text: "Namespace configuration deleted successfully" - }); - setIsDeleteModalOpen(false); - setConfigToDelete(null); - } catch (error) { - console.error("Failed to delete namespace config:", error); - createNotification({ - type: "error", - text: "Failed to delete namespace configuration" - }); - } + await deleteConfig({ id: configToDelete.id }); + createNotification({ + type: "success", + text: "Namespace configuration deleted successfully" + }); + setIsDeleteModalOpen(false); + setConfigToDelete(null); }; const getConnectionName = (connectionId: string | null) => { diff --git a/frontend/src/pages/organization/SettingsPage/components/ExternalMigrationsTab/components/VaultNamespaceConfigModal.tsx b/frontend/src/pages/organization/SettingsPage/components/ExternalMigrationsTab/components/VaultNamespaceConfigModal.tsx index 62fb78b48..f08aae204 100644 --- a/frontend/src/pages/organization/SettingsPage/components/ExternalMigrationsTab/components/VaultNamespaceConfigModal.tsx +++ b/frontend/src/pages/organization/SettingsPage/components/ExternalMigrationsTab/components/VaultNamespaceConfigModal.tsx @@ -74,36 +74,28 @@ export const VaultNamespaceConfigModal = ({ isOpen, onOpenChange, editConfig }: }, [isOpen, editConfig, reset]); const onFormSubmit = async (data: FormData) => { - try { - if (isEdit && editConfig) { - await updateConfig({ - id: editConfig.id, - namespace: data.namespace, - connectionId: data.connectionId - }); - createNotification({ - type: "success", - text: "Namespace configuration updated successfully" - }); - } else { - await createConfig({ - namespace: data.namespace, - connectionId: data.connectionId - }); - createNotification({ - type: "success", - text: "Namespace configuration created successfully" - }); - } - reset(); - onOpenChange(false); - } catch (error) { - console.error("Failed to save namespace config:", error); + if (isEdit && editConfig) { + await updateConfig({ + id: editConfig.id, + namespace: data.namespace, + connectionId: data.connectionId + }); createNotification({ - type: "error", - text: `Failed to ${isEdit ? "update" : "create"} namespace configuration` + type: "success", + text: "Namespace configuration updated successfully" + }); + } else { + await createConfig({ + namespace: data.namespace, + connectionId: data.connectionId + }); + createNotification({ + type: "success", + text: "Namespace configuration created successfully" }); } + reset(); + onOpenChange(false); }; const handleClose = () => { diff --git a/frontend/src/pages/organization/SettingsPage/components/OrgDeleteSection/OrgDeleteSection.tsx b/frontend/src/pages/organization/SettingsPage/components/OrgDeleteSection/OrgDeleteSection.tsx index 4dfe89f71..6e5c0e1cb 100644 --- a/frontend/src/pages/organization/SettingsPage/components/OrgDeleteSection/OrgDeleteSection.tsx +++ b/frontend/src/pages/organization/SettingsPage/components/OrgDeleteSection/OrgDeleteSection.tsx @@ -19,27 +19,19 @@ export const OrgDeleteSection = () => { const { mutateAsync, isPending } = useDeleteOrgById(); const handleDeleteOrgSubmit = async () => { - try { - if (!currentOrg?.id) return; + if (!currentOrg?.id) return; - await mutateAsync({ - organizationId: currentOrg?.id - }); + await mutateAsync({ + organizationId: currentOrg?.id + }); - createNotification({ - text: "Successfully deleted organization", - type: "success" - }); + createNotification({ + text: "Successfully deleted organization", + type: "success" + }); - clearSession(); - navigate({ to: "/login" }); - } catch (err) { - console.error(err); - createNotification({ - text: "Failed to delete organization", - type: "error" - }); - } + clearSession(); + navigate({ to: "/login" }); }; return ( diff --git a/frontend/src/pages/organization/SettingsPage/components/OrgEncryptionTab/OrgEncryptionTab.tsx b/frontend/src/pages/organization/SettingsPage/components/OrgEncryptionTab/OrgEncryptionTab.tsx index 564b08969..81649b604 100644 --- a/frontend/src/pages/organization/SettingsPage/components/OrgEncryptionTab/OrgEncryptionTab.tsx +++ b/frontend/src/pages/organization/SettingsPage/components/OrgEncryptionTab/OrgEncryptionTab.tsx @@ -51,18 +51,14 @@ export const OrgEncryptionTab = withPermission( kmsId: string; }; - try { - await removeExternalKms(kmsId); + await removeExternalKms(kmsId); - createNotification({ - text: "Successfully deleted external KMS", - type: "success" - }); + createNotification({ + text: "Successfully deleted external KMS", + type: "success" + }); - handlePopUpToggle("removeExternalKms", false); - } catch (err) { - console.error(err); - } + handlePopUpToggle("removeExternalKms", false); }; return ( diff --git a/frontend/src/pages/organization/SettingsPage/components/OrgIncidentContactsSection/AddOrgIncidentContactModal.tsx b/frontend/src/pages/organization/SettingsPage/components/OrgIncidentContactsSection/AddOrgIncidentContactModal.tsx index 84bb083ec..125a3f310 100644 --- a/frontend/src/pages/organization/SettingsPage/components/OrgIncidentContactsSection/AddOrgIncidentContactModal.tsx +++ b/frontend/src/pages/organization/SettingsPage/components/OrgIncidentContactsSection/AddOrgIncidentContactModal.tsx @@ -35,31 +35,23 @@ export const AddOrgIncidentContactModal = ({ const { mutateAsync, isPending } = useAddIncidentContact(); const onFormSubmit = async ({ email }: TAddContactForm) => { - try { - if (!currentOrg?.id) return; + if (!currentOrg?.id) return; - await mutateAsync({ - orgId: currentOrg.id, - email - }); + await mutateAsync({ + orgId: currentOrg.id, + email + }); - createNotification({ - text: "Successfully added incident contact", - type: "success" - }); + createNotification({ + text: "Successfully added incident contact", + type: "success" + }); - if (serverDetails?.emailConfigured) { - handlePopUpClose("addContact"); - } - - reset(); - } catch (err) { - console.error(err); - createNotification({ - text: "Failed to add incident contact", - type: "error" - }); + if (serverDetails?.emailConfigured) { + handlePopUpClose("addContact"); } + + reset(); }; return ( diff --git a/frontend/src/pages/organization/SettingsPage/components/OrgIncidentContactsSection/OrgIncidentContactsTable.tsx b/frontend/src/pages/organization/SettingsPage/components/OrgIncidentContactsSection/OrgIncidentContactsTable.tsx index d0723fdaf..c16431b9c 100644 --- a/frontend/src/pages/organization/SettingsPage/components/OrgIncidentContactsSection/OrgIncidentContactsTable.tsx +++ b/frontend/src/pages/organization/SettingsPage/components/OrgIncidentContactsSection/OrgIncidentContactsTable.tsx @@ -33,28 +33,20 @@ export const OrgIncidentContactsTable = () => { const { mutateAsync } = useDeleteIncidentContact(); const onRemoveIncidentContact = async () => { - try { - const incidentContactId = (popUp?.removeContact?.data as { id: string })?.id; + const incidentContactId = (popUp?.removeContact?.data as { id: string })?.id; - if (!currentOrg?.id) return; - await mutateAsync({ - orgId: currentOrg.id, - incidentContactId - }); + if (!currentOrg?.id) return; + await mutateAsync({ + orgId: currentOrg.id, + incidentContactId + }); - createNotification({ - text: "Successfully removed incident contact", - type: "success" - }); + createNotification({ + text: "Successfully removed incident contact", + type: "success" + }); - handlePopUpClose("removeContact"); - } catch (err) { - console.error(err); - createNotification({ - text: "Failed to remove incident contact", - type: "error" - }); - } + handlePopUpClose("removeContact"); }; const filteredContacts = contacts diff --git a/frontend/src/pages/organization/SettingsPage/components/OrgNameChangeSection/OrgNameChangeSection.tsx b/frontend/src/pages/organization/SettingsPage/components/OrgNameChangeSection/OrgNameChangeSection.tsx index 766a22158..03fb14dc7 100644 --- a/frontend/src/pages/organization/SettingsPage/components/OrgNameChangeSection/OrgNameChangeSection.tsx +++ b/frontend/src/pages/organization/SettingsPage/components/OrgNameChangeSection/OrgNameChangeSection.tsx @@ -56,27 +56,19 @@ export const OrgNameChangeSection = (): JSX.Element => { }, [roles]); const onFormSubmit = async ({ name, slug, defaultMembershipRole }: FormData) => { - try { - if (!currentOrg?.id || !roles?.length) return; + if (!currentOrg?.id || !roles?.length) return; - await mutateAsync({ - orgId: currentOrg?.id, - name, - slug, - defaultMembershipRoleSlug: defaultMembershipRole - }); + await mutateAsync({ + orgId: currentOrg?.id, + name, + slug, + defaultMembershipRoleSlug: defaultMembershipRole + }); - createNotification({ - text: "Successfully updated organization details", - type: "success" - }); - } catch (error) { - console.error(error); - createNotification({ - text: "Failed to update organization details", - type: "error" - }); - } + createNotification({ + text: "Successfully updated organization details", + type: "success" + }); }; if (!isFormInitialized) { diff --git a/frontend/src/pages/organization/SettingsPage/components/OrgNameChangeSection/SubOrgNameChangeSection.tsx b/frontend/src/pages/organization/SettingsPage/components/OrgNameChangeSection/SubOrgNameChangeSection.tsx index ca625be6c..e08d4d1b5 100644 --- a/frontend/src/pages/organization/SettingsPage/components/OrgNameChangeSection/SubOrgNameChangeSection.tsx +++ b/frontend/src/pages/organization/SettingsPage/components/OrgNameChangeSection/SubOrgNameChangeSection.tsx @@ -39,26 +39,18 @@ export const SubOrgNameChangeSection = (): JSX.Element => { const { mutateAsync, isPending } = useUpdateSubOrganization(); const onFormSubmit = async ({ name }: FormData) => { - try { - await mutateAsync({ - name, - subOrgId: currentOrg.id - }); + await mutateAsync({ + name, + subOrgId: currentOrg.id + }); - navigate({ to: "/organization/settings", search: { subOrganization: name } }); - queryClient.invalidateQueries(); - await router.invalidate({ sync: true }); - createNotification({ - text: "Successfully updated sub-organization details", - type: "success" - }); - } catch (error) { - console.error(error); - createNotification({ - text: "Failed to update sub-organization details", - type: "error" - }); - } + navigate({ to: "/organization/settings", search: { subOrganization: name } }); + queryClient.invalidateQueries(); + await router.invalidate({ sync: true }); + createNotification({ + text: "Successfully updated sub-organization details", + type: "success" + }); }; return ( diff --git a/frontend/src/pages/organization/SettingsPage/components/OrgProductSelectSection/OrgProductSelectSection.tsx b/frontend/src/pages/organization/SettingsPage/components/OrgProductSelectSection/OrgProductSelectSection.tsx index 5be15edad..e1fc2712d 100644 --- a/frontend/src/pages/organization/SettingsPage/components/OrgProductSelectSection/OrgProductSelectSection.tsx +++ b/frontend/src/pages/organization/SettingsPage/components/OrgProductSelectSection/OrgProductSelectSection.tsx @@ -1,7 +1,5 @@ import { useEffect, useState } from "react"; -import axios from "axios"; -import { createNotification } from "@app/components/notifications"; import { Switch } from "@app/components/v2"; import { useOrganization } from "@app/context"; import { useUpdateOrg } from "@app/hooks/api"; @@ -60,20 +58,10 @@ export const OrgProductSelectSection = () => { [key]: { ...products[key], enabled: value } })); - try { - await mutateAsync({ - orgId: currentOrg.id, - [key]: value - }); - } catch (e) { - if (axios.isAxiosError(e)) { - const { message = "Something went wrong" } = e.response?.data as { message: string }; - createNotification({ - type: "error", - text: message - }); - } - } + await mutateAsync({ + orgId: currentOrg.id, + [key]: value + }); setIsLoading(false); }; diff --git a/frontend/src/pages/organization/SettingsPage/components/OrgProductSettingsTab/OrgProductSettingsTab.tsx b/frontend/src/pages/organization/SettingsPage/components/OrgProductSettingsTab/OrgProductSettingsTab.tsx index e4d935996..95cc7b870 100644 --- a/frontend/src/pages/organization/SettingsPage/components/OrgProductSettingsTab/OrgProductSettingsTab.tsx +++ b/frontend/src/pages/organization/SettingsPage/components/OrgProductSettingsTab/OrgProductSettingsTab.tsx @@ -30,12 +30,6 @@ export const OrgProductSettingsTab = () => { text: `Successfully ${state ? "enabled" : "disabled"} blocking duplicate secret sync destinations for this organization`, type: "success" }); - } catch (err) { - console.error(err); - createNotification({ - text: "Failed to update blocking duplicate secret sync destinations setting for this organization", - type: "error" - }); } finally { setIsLoading(false); } diff --git a/frontend/src/pages/organization/SettingsPage/components/OrgProvisioningTab/ExternalGroupOrgRoleMappings.tsx b/frontend/src/pages/organization/SettingsPage/components/OrgProvisioningTab/ExternalGroupOrgRoleMappings.tsx index 8e181e8c4..bc9a02921 100644 --- a/frontend/src/pages/organization/SettingsPage/components/OrgProvisioningTab/ExternalGroupOrgRoleMappings.tsx +++ b/frontend/src/pages/organization/SettingsPage/components/OrgProvisioningTab/ExternalGroupOrgRoleMappings.tsx @@ -75,19 +75,11 @@ export const ExternalGroupOrgRoleMappings = () => { const mappingField = useFieldArray({ control, name: "mappings" }); const handleUpdateMappings = async (form: TForm) => { - try { - await updateMappings.mutateAsync(form); - createNotification({ - text: "Group organization role mappings updated.", - type: "success" - }); - } catch (e) { - console.error(e); - createNotification({ - text: "Failed to update group organization role mappings.", - type: "error" - }); - } + await updateMappings.mutateAsync(form); + createNotification({ + text: "Group organization role mappings updated.", + type: "success" + }); }; const disableScimEdit = permission.cannot(OrgPermissionActions.Edit, OrgPermissionSubjects.Scim); diff --git a/frontend/src/pages/organization/SettingsPage/components/OrgProvisioningTab/GithubOrgSyncConfigModal.tsx b/frontend/src/pages/organization/SettingsPage/components/OrgProvisioningTab/GithubOrgSyncConfigModal.tsx index 180b63278..868dd17f7 100644 --- a/frontend/src/pages/organization/SettingsPage/components/OrgProvisioningTab/GithubOrgSyncConfigModal.tsx +++ b/frontend/src/pages/organization/SettingsPage/components/OrgProvisioningTab/GithubOrgSyncConfigModal.tsx @@ -55,55 +55,40 @@ export const GithubOrgSyncConfigModal = ({ }); const onFormSubmit = async ({ githubOrgName, githubOrgAccessToken }: FormData) => { - try { - if (isUpdate) { - await updateGithubSyncOrgConfig({ - githubOrgName, - githubOrgAccessToken - }); + if (isUpdate) { + await updateGithubSyncOrgConfig({ + githubOrgName, + githubOrgAccessToken + }); - createNotification({ - text: "Successfully updated GitHub Organization Sync", - type: "success" - }); - } else { - await createGithubSyncOrgConfig({ - githubOrgName, - githubOrgAccessToken, - isActive: false - }); - - createNotification({ - text: "Successfully created GitHub Organization Sync", - type: "success" - }); - } - handlePopUpToggle("githubOrgSyncConfig"); - } catch { createNotification({ - text: "Failed to setup GitHub Organization Sync", - type: "error" + text: "Successfully updated GitHub Organization Sync", + type: "success" + }); + } else { + await createGithubSyncOrgConfig({ + githubOrgName, + githubOrgAccessToken, + isActive: false + }); + + createNotification({ + text: "Successfully created GitHub Organization Sync", + type: "success" }); } + handlePopUpToggle("githubOrgSyncConfig"); }; const onDelete = async () => { - try { - await deleteGithubSyncOrgConfig(); + await deleteGithubSyncOrgConfig(); - handlePopUpToggle("deleteGithubOrgSyncConfig", false); - handlePopUpToggle("githubOrgSyncConfig", false); - createNotification({ - text: "Successfully deleted GitHub Organization Sync", - type: "success" - }); - } catch (err) { - console.error(err); - createNotification({ - text: "Failed to delete GitHub Organization Sync", - type: "error" - }); - } + handlePopUpToggle("deleteGithubOrgSyncConfig", false); + handlePopUpToggle("githubOrgSyncConfig", false); + createNotification({ + text: "Successfully deleted GitHub Organization Sync", + type: "success" + }); }; return ( diff --git a/frontend/src/pages/organization/SettingsPage/components/OrgProvisioningTab/OrgGithubSyncSection.tsx b/frontend/src/pages/organization/SettingsPage/components/OrgProvisioningTab/OrgGithubSyncSection.tsx index 105f8eb8e..f2115df96 100644 --- a/frontend/src/pages/organization/SettingsPage/components/OrgProvisioningTab/OrgGithubSyncSection.tsx +++ b/frontend/src/pages/organization/SettingsPage/components/OrgProvisioningTab/OrgGithubSyncSection.tsx @@ -35,64 +35,41 @@ export const OrgGithubSyncSection = () => { const data = !isPending && !githubOrgSyncConfig?.isError ? githubOrgSyncConfig?.data : undefined; const handleBulkSync = async () => { - try { - const result = await syncAllTeamsMutation.mutateAsync(); - let message = "Successfully synced teams"; + const result = await syncAllTeamsMutation.mutateAsync(); + let message = "Successfully synced teams"; - const details = []; - if (result.createdTeams.length > 0) { - details.push( - `${result.createdTeams.length} new team${result.createdTeams.length === 1 ? "" : "s"} created` - ); - } - if (result.updatedTeams.length > 0) { - details.push( - `${result.updatedTeams.length} team${result.updatedTeams.length === 1 ? "" : "s"} updated` - ); - } - if (result.removedMemberships > 0) { - details.push( - `${result.removedMemberships} membership${result.removedMemberships === 1 ? "" : "s"} removed` - ); - } + const details = []; + if (result.createdTeams.length > 0) { + details.push( + `${result.createdTeams.length} new team${result.createdTeams.length === 1 ? "" : "s"} created` + ); + } + if (result.updatedTeams.length > 0) { + details.push( + `${result.updatedTeams.length} team${result.updatedTeams.length === 1 ? "" : "s"} updated` + ); + } + if (result.removedMemberships > 0) { + details.push( + `${result.removedMemberships} membership${result.removedMemberships === 1 ? "" : "s"} removed` + ); + } - if (details.length > 0) { - message += `. ${details.join(", ")}`; - } + if (details.length > 0) { + message += `. ${details.join(", ")}`; + } + createNotification({ + text: message, + type: "success" + }); + + if (result.errors && result.errors.length > 0) { createNotification({ - text: message, - type: "success" + text: `Sync completed with ${result.errors.length} warnings. Check the console for details.`, + type: "warning" }); - - if (result.errors && result.errors.length > 0) { - createNotification({ - text: `Sync completed with ${result.errors.length} warnings. Check the console for details.`, - type: "warning" - }); - console.warn("Sync errors:", result.errors); - } - } catch (error) { - const errorMessage = - (error as any)?.response?.data?.message || (error as Error)?.message || "Unknown error"; - - if ( - errorMessage.includes("token") && - (errorMessage.includes("required") || - errorMessage.includes("invalid") || - errorMessage.includes("expired") || - errorMessage.includes("set a token first")) - ) { - createNotification({ - text: "Please set a GitHub access token in the configuration modal to continue with the sync", - type: "error" - }); - } else { - createNotification({ - text: `Failed to sync GitHub teams: ${errorMessage}`, - type: "error" - }); - } + console.warn("Sync errors:", result.errors); } }; diff --git a/frontend/src/pages/organization/SettingsPage/components/OrgProvisioningTab/OrgSCIMSection.tsx b/frontend/src/pages/organization/SettingsPage/components/OrgProvisioningTab/OrgSCIMSection.tsx index 4ba89683c..f7551d1e4 100644 --- a/frontend/src/pages/organization/SettingsPage/components/OrgProvisioningTab/OrgSCIMSection.tsx +++ b/frontend/src/pages/organization/SettingsPage/components/OrgProvisioningTab/OrgSCIMSection.tsx @@ -36,30 +36,23 @@ export const OrgScimSection = () => { }; const handleEnableSCIMToggle = async (value: boolean) => { - try { - if (!currentOrg?.id) return; - if (!subscription?.scim) { - handlePopUpOpen("upgradePlan", { - isEnterpriseFeature: true - }); - return; - } - - await mutateAsync({ - orgId: currentOrg?.id, - scimEnabled: value - }); - - createNotification({ - text: `Successfully ${value ? "enabled" : "disabled"} SCIM provisioning`, - type: "success" - }); - } catch (err) { - createNotification({ - text: (err as { response: { data: { message: string } } }).response.data.message, - type: "error" + if (!currentOrg?.id) return; + if (!subscription?.scim) { + handlePopUpOpen("upgradePlan", { + isEnterpriseFeature: true }); + return; } + + await mutateAsync({ + orgId: currentOrg?.id, + scimEnabled: value + }); + + createNotification({ + text: `Successfully ${value ? "enabled" : "disabled"} SCIM provisioning`, + type: "success" + }); }; return ( diff --git a/frontend/src/pages/organization/SettingsPage/components/OrgProvisioningTab/ScimTokenModal.tsx b/frontend/src/pages/organization/SettingsPage/components/OrgProvisioningTab/ScimTokenModal.tsx index c542a88bb..5d6007ac0 100644 --- a/frontend/src/pages/organization/SettingsPage/components/OrgProvisioningTab/ScimTokenModal.tsx +++ b/frontend/src/pages/organization/SettingsPage/components/OrgProvisioningTab/ScimTokenModal.tsx @@ -92,52 +92,36 @@ export const ScimTokenModal = ({ popUp, handlePopUpOpen, handlePopUpToggle }: Pr }, [isScimTokenCopied, isScimUrlCopied]); const onFormSubmit = async ({ description, ttlDays }: FormData) => { - try { - if (!currentOrg?.id) return; + if (!currentOrg?.id) return; - const { scimToken } = await createScimTokenMutateAsync({ - organizationId: currentOrg.id, - description, - ttlDays: Number(ttlDays) - }); + const { scimToken } = await createScimTokenMutateAsync({ + organizationId: currentOrg.id, + description, + ttlDays: Number(ttlDays) + }); - setToken(scimToken); + setToken(scimToken); - createNotification({ - text: "Successfully created SCIM token", - type: "success" - }); - } catch (err) { - console.error(err); - createNotification({ - text: "Failed to create SCIM token", - type: "error" - }); - } + createNotification({ + text: "Successfully created SCIM token", + type: "success" + }); }; const onDeleteScimTokenSubmit = async (scimTokenId: string) => { - try { - if (!currentOrg?.id) return; + if (!currentOrg?.id) return; - await deleteScimTokenMutateAsync({ - organizationId: currentOrg.id, - scimTokenId - }); + await deleteScimTokenMutateAsync({ + organizationId: currentOrg.id, + scimTokenId + }); - handlePopUpToggle("deleteScimToken", false); + handlePopUpToggle("deleteScimToken", false); - createNotification({ - text: "Successfully deleted SCIM token", - type: "success" - }); - } catch (err) { - console.error(err); - createNotification({ - text: "Failed to delete SCIM token", - type: "error" - }); - } + createNotification({ + text: "Successfully deleted SCIM token", + type: "success" + }); }; const hasToken = Boolean(token); diff --git a/frontend/src/pages/organization/SettingsPage/components/OrgSecurityTab/OrgGenericAuthSection.tsx b/frontend/src/pages/organization/SettingsPage/components/OrgSecurityTab/OrgGenericAuthSection.tsx index 1500098e9..7e6922318 100644 --- a/frontend/src/pages/organization/SettingsPage/components/OrgSecurityTab/OrgGenericAuthSection.tsx +++ b/frontend/src/pages/organization/SettingsPage/components/OrgSecurityTab/OrgGenericAuthSection.tsx @@ -20,55 +20,39 @@ export const OrgGenericAuthSection = () => { const { mutateAsync } = useUpdateOrg(); const handleEnforceMfaToggle = async (value: boolean) => { - try { - if (!currentOrg?.id) return; - if (!subscription?.enforceMfa) { - handlePopUpOpen("upgradePlan"); - return; - } - - await mutateAsync({ - orgId: currentOrg?.id, - enforceMfa: value - }); - - createNotification({ - text: `Successfully ${value ? "enforced" : "un-enforced"} MFA`, - type: "success" - }); - } catch (err) { - console.error(err); - createNotification({ - text: (err as { response: { data: { message: string } } }).response.data.message, - type: "error" - }); + if (!currentOrg?.id) return; + if (!subscription?.enforceMfa) { + handlePopUpOpen("upgradePlan"); + return; } + + await mutateAsync({ + orgId: currentOrg?.id, + enforceMfa: value + }); + + createNotification({ + text: `Successfully ${value ? "enforced" : "un-enforced"} MFA`, + type: "success" + }); }; const handleUpdateSelectedMfa = async (selectedMfaMethod: MfaMethod) => { - try { - if (!currentOrg?.id) return; - if (!subscription?.enforceMfa) { - handlePopUpOpen("upgradePlan"); - return; - } - - await mutateAsync({ - orgId: currentOrg?.id, - selectedMfaMethod - }); - - createNotification({ - text: "Successfully updated selected MFA method", - type: "success" - }); - } catch (err) { - console.error(err); - createNotification({ - text: (err as { response: { data: { message: string } } }).response.data.message, - type: "error" - }); + if (!currentOrg?.id) return; + if (!subscription?.enforceMfa) { + handlePopUpOpen("upgradePlan"); + return; } + + await mutateAsync({ + orgId: currentOrg?.id, + selectedMfaMethod + }); + + createNotification({ + text: "Successfully updated selected MFA method", + type: "success" + }); }; return ( diff --git a/frontend/src/pages/organization/SettingsPage/components/OrgSecurityTab/OrgUserAccessTokenLimitSection.tsx b/frontend/src/pages/organization/SettingsPage/components/OrgSecurityTab/OrgUserAccessTokenLimitSection.tsx index 6e9865532..c78b5475e 100644 --- a/frontend/src/pages/organization/SettingsPage/components/OrgSecurityTab/OrgUserAccessTokenLimitSection.tsx +++ b/frontend/src/pages/organization/SettingsPage/components/OrgSecurityTab/OrgUserAccessTokenLimitSection.tsx @@ -57,24 +57,17 @@ export const OrgUserAccessTokenLimitSection = () => { if (!currentOrg) return null; const handleUserTokenExpirationSubmit = async (formData: TForm) => { - try { - const userTokenExpiration = formatDuration(formData.expirationValue, formData.expirationUnit); + const userTokenExpiration = formatDuration(formData.expirationValue, formData.expirationUnit); - await updateUserTokenExpiration({ - userTokenExpiration, - orgId: currentOrg.id - }); + await updateUserTokenExpiration({ + userTokenExpiration, + orgId: currentOrg.id + }); - createNotification({ - text: "Successfully updated user token expiration", - type: "success" - }); - } catch { - createNotification({ - text: "Failed updating user token expiration", - type: "error" - }); - } + createNotification({ + text: "Successfully updated user token expiration", + type: "success" + }); }; // Units for the dropdown with readable labels diff --git a/frontend/src/pages/organization/SettingsPage/components/OrgSsoTab/LDAPGroupMapModal.tsx b/frontend/src/pages/organization/SettingsPage/components/OrgSsoTab/LDAPGroupMapModal.tsx index aee845187..31e96a1cb 100644 --- a/frontend/src/pages/organization/SettingsPage/components/OrgSsoTab/LDAPGroupMapModal.tsx +++ b/frontend/src/pages/organization/SettingsPage/components/OrgSsoTab/LDAPGroupMapModal.tsx @@ -79,28 +79,20 @@ export const LDAPGroupMapModal = ({ popUp, handlePopUpOpen, handlePopUpToggle }: }); const onFormSubmit = async ({ groupSlug, ldapGroupCN }: TFormData) => { - try { - if (!ldapConfig) return; + if (!ldapConfig) return; - await createLDAPGroupMapping({ - ldapConfigId: ldapConfig.id, - groupSlug, - ldapGroupCN - }); + await createLDAPGroupMapping({ + ldapConfigId: ldapConfig.id, + groupSlug, + ldapGroupCN + }); - reset(); + reset(); - createNotification({ - text: `Successfully added LDAP group mapping for ${ldapGroupCN}`, - type: "success" - }); - } catch (err) { - console.error(err); - createNotification({ - text: `Failed to add LDAP group mapping for ${ldapGroupCN}`, - type: "error" - }); - } + createNotification({ + text: `Successfully added LDAP group mapping for ${ldapGroupCN}`, + type: "success" + }); }; const onDeleteGroupMapSubmit = async ({ @@ -112,25 +104,17 @@ export const LDAPGroupMapModal = ({ popUp, handlePopUpOpen, handlePopUpToggle }: ldapGroupMapId: string; ldapGroupCN: string; }) => { - try { - await deleteLDAPGroupMapping({ - ldapConfigId, - ldapGroupMapId - }); + await deleteLDAPGroupMapping({ + ldapConfigId, + ldapGroupMapId + }); - handlePopUpToggle("deleteLdapGroupMap", false); + handlePopUpToggle("deleteLdapGroupMap", false); - createNotification({ - text: `Successfully deleted LDAP group mapping ${ldapGroupCN}`, - type: "success" - }); - } catch (err) { - console.error(err); - createNotification({ - text: `Failed to delete LDAP group mapping ${ldapGroupCN}`, - type: "error" - }); - } + createNotification({ + text: `Successfully deleted LDAP group mapping ${ldapGroupCN}`, + type: "success" + }); }; useEffect(() => { diff --git a/frontend/src/pages/organization/SettingsPage/components/OrgSsoTab/LDAPModal.tsx b/frontend/src/pages/organization/SettingsPage/components/OrgSsoTab/LDAPModal.tsx index 580ecdeb1..01429f512 100644 --- a/frontend/src/pages/organization/SettingsPage/components/OrgSsoTab/LDAPModal.tsx +++ b/frontend/src/pages/organization/SettingsPage/components/OrgSsoTab/LDAPModal.tsx @@ -62,31 +62,24 @@ export const LDAPModal = ({ popUp, handlePopUpClose, handlePopUpToggle, hideDele if (!currentOrg) { return; } - try { - await updateMutateAsync({ - organizationId: currentOrg.id, - isActive: false, - url: "", - bindDN: "", - bindPass: "", - searchBase: "", - searchFilter: "", - uniqueUserAttribute: "", - groupSearchBase: "", - groupSearchFilter: "", - caCert: "" - }); + await updateMutateAsync({ + organizationId: currentOrg.id, + isActive: false, + url: "", + bindDN: "", + bindPass: "", + searchBase: "", + searchFilter: "", + uniqueUserAttribute: "", + groupSearchBase: "", + groupSearchFilter: "", + caCert: "" + }); - createNotification({ - text: "Successfully deleted OIDC configuration.", - type: "success" - }); - } catch { - createNotification({ - text: "Failed deleting OIDC configuration.", - type: "error" - }); - } + createNotification({ + text: "Successfully deleted OIDC configuration.", + type: "success" + }); }; const watchUrl = watch("url"); @@ -122,83 +115,59 @@ export const LDAPModal = ({ popUp, handlePopUpClose, handlePopUpToggle, hideDele caCert, shouldCloseModal = true }: TLDAPFormData & { shouldCloseModal?: boolean }) => { - try { - if (!currentOrg) return; + if (!currentOrg) return; - if (!data) { - await createMutateAsync({ - organizationId: currentOrg.id, - isActive: false, - url, - bindDN, - bindPass, - searchBase, - searchFilter, - uniqueUserAttribute, - groupSearchBase, - groupSearchFilter, - caCert - }); - } else { - await updateMutateAsync({ - organizationId: currentOrg.id, - url, - bindDN, - bindPass, - searchBase, - searchFilter, - uniqueUserAttribute, - groupSearchBase, - groupSearchFilter, - caCert - }); - } - - if (shouldCloseModal) { - handlePopUpClose("addLDAP"); - } - - createNotification({ - text: `Successfully ${!data ? "added" : "updated"} LDAP configuration`, - type: "success" + if (!data) { + await createMutateAsync({ + organizationId: currentOrg.id, + isActive: false, + url, + bindDN, + bindPass, + searchBase, + searchFilter, + uniqueUserAttribute, + groupSearchBase, + groupSearchFilter, + caCert }); - } catch (err) { - console.error(err); - createNotification({ - text: `Failed to ${!data ? "add" : "update"} LDAP configuration`, - type: "error" + } else { + await updateMutateAsync({ + organizationId: currentOrg.id, + url, + bindDN, + bindPass, + searchBase, + searchFilter, + uniqueUserAttribute, + groupSearchBase, + groupSearchFilter, + caCert }); } + + if (shouldCloseModal) { + handlePopUpClose("addLDAP"); + } + + createNotification({ + text: `Successfully ${!data ? "added" : "updated"} LDAP configuration`, + type: "success" + }); }; const handleTestLDAPConnection = async () => { - try { - const result = await testLDAPConnection({ - url: watchUrl, - bindDN: watchBindDN, - bindPass: watchBindPass, - caCert: watchCaCert ?? "" - }); + await testLDAPConnection({ + url: watchUrl, + bindDN: watchBindDN, + bindPass: watchBindPass, + caCert: watchCaCert ?? "" + }); - if (!result) { - createNotification({ - text: "Failed to test the LDAP connection: Bind operation was unsuccessful", - type: "error" - }); - return; - } - - createNotification({ - text: "Successfully tested the LDAP connection: Bind operation was successful", - type: "success" - }); - } catch (err) { - console.error(err); - createNotification({ - text: "Failed to test the LDAP connection", - type: "error" - }); - } + createNotification({ + text: "Successfully tested the LDAP connection: Bind operation was successful", + type: "success" + }); }; return ( diff --git a/frontend/src/pages/organization/SettingsPage/components/OrgSsoTab/OIDCModal.tsx b/frontend/src/pages/organization/SettingsPage/components/OrgSsoTab/OIDCModal.tsx index 03f946ace..f980b2e4f 100644 --- a/frontend/src/pages/organization/SettingsPage/components/OrgSsoTab/OIDCModal.tsx +++ b/frontend/src/pages/organization/SettingsPage/components/OrgSsoTab/OIDCModal.tsx @@ -122,31 +122,24 @@ export const OIDCModal = ({ popUp, handlePopUpClose, handlePopUpToggle, hideDele if (!currentOrg) { return; } - try { - await updateMutateAsync({ - issuer: "", - discoveryURL: "", - authorizationEndpoint: "", - allowedEmailDomains: "", - jwksUri: "", - tokenEndpoint: "", - userinfoEndpoint: "", - clientId: "", - clientSecret: "", - isActive: false, - organizationId: currentOrg.id - }); + await updateMutateAsync({ + issuer: "", + discoveryURL: "", + authorizationEndpoint: "", + allowedEmailDomains: "", + jwksUri: "", + tokenEndpoint: "", + userinfoEndpoint: "", + clientId: "", + clientSecret: "", + isActive: false, + organizationId: currentOrg.id + }); - createNotification({ - text: "Successfully deleted OIDC configuration.", - type: "success" - }); - } catch { - createNotification({ - text: "Failed deleting OIDC configuration.", - type: "error" - }); - } + createNotification({ + text: "Successfully deleted OIDC configuration.", + type: "success" + }); }; useEffect(() => { @@ -178,58 +171,50 @@ export const OIDCModal = ({ popUp, handlePopUpClose, handlePopUpToggle, hideDele clientSecret, jwtSignatureAlgorithm }: OIDCFormData) => { - try { - if (!currentOrg) { - return; - } + if (!currentOrg) { + return; + } - if (!data) { - await createMutateAsync({ - issuer, - configurationType, - discoveryURL, - authorizationEndpoint, - allowedEmailDomains, - jwksUri, - tokenEndpoint, - userinfoEndpoint, - clientId, - clientSecret, - isActive: true, - organizationId: currentOrg.id, - jwtSignatureAlgorithm - }); - } else { - await updateMutateAsync({ - issuer, - configurationType, - discoveryURL, - authorizationEndpoint, - allowedEmailDomains, - jwksUri, - tokenEndpoint, - userinfoEndpoint, - clientId, - clientSecret, - isActive: true, - organizationId: currentOrg.id, - jwtSignatureAlgorithm - }); - } - - handlePopUpClose("addOIDC"); - - createNotification({ - text: `Successfully ${!data ? "added" : "updated"} OIDC SSO configuration`, - type: "success" + if (!data) { + await createMutateAsync({ + issuer, + configurationType, + discoveryURL, + authorizationEndpoint, + allowedEmailDomains, + jwksUri, + tokenEndpoint, + userinfoEndpoint, + clientId, + clientSecret, + isActive: true, + organizationId: currentOrg.id, + jwtSignatureAlgorithm }); - } catch (err) { - console.error(err); - createNotification({ - text: `Failed to ${!data ? "add" : "update"} OIDC SSO configuration`, - type: "error" + } else { + await updateMutateAsync({ + issuer, + configurationType, + discoveryURL, + authorizationEndpoint, + allowedEmailDomains, + jwksUri, + tokenEndpoint, + userinfoEndpoint, + clientId, + clientSecret, + isActive: true, + organizationId: currentOrg.id, + jwtSignatureAlgorithm }); } + + handlePopUpClose("addOIDC"); + + createNotification({ + text: `Successfully ${!data ? "added" : "updated"} OIDC SSO configuration`, + type: "success" + }); }; return ( diff --git a/frontend/src/pages/organization/SettingsPage/components/OrgSsoTab/OrgGeneralAuthSection.tsx b/frontend/src/pages/organization/SettingsPage/components/OrgSsoTab/OrgGeneralAuthSection.tsx index 5be97dc1b..d35a04323 100644 --- a/frontend/src/pages/organization/SettingsPage/components/OrgSsoTab/OrgGeneralAuthSection.tsx +++ b/frontend/src/pages/organization/SettingsPage/components/OrgSsoTab/OrgGeneralAuthSection.tsx @@ -45,69 +45,61 @@ export const OrgGeneralAuthSection = ({ const logout = useLogoutUser(); const handleEnforceOrgAuthToggle = async (value: boolean, type: EnforceAuthType) => { - try { - if (!currentOrg?.id) return; + if (!currentOrg?.id) return; - if (type === EnforceAuthType.SAML) { - if (!subscription?.samlSSO) { - handlePopUpOpen("upgradePlan"); - return; - } - - await mutateAsync({ - orgId: currentOrg?.id, - authEnforced: value - }); - } else if (type === EnforceAuthType.GOOGLE) { - if (!subscription?.enforceGoogleSSO) { - handlePopUpOpen("upgradePlan"); - return; - } - - await mutateAsync({ - orgId: currentOrg?.id, - googleSsoAuthEnforced: value - }); - } else if (type === EnforceAuthType.OIDC) { - if (!subscription?.oidcSSO) { - handlePopUpOpen("upgradePlan"); - return; - } - - await mutateAsync({ - orgId: currentOrg?.id, - authEnforced: value - }); - } else { - createNotification({ - text: `Invalid auth enforcement type ${type}`, - type: "error" - }); + if (type === EnforceAuthType.SAML) { + if (!subscription?.samlSSO) { + handlePopUpOpen("upgradePlan"); + return; } - createNotification({ - text: `Successfully ${value ? "enabled" : "disabled"} org-level auth`, - type: "success" + await mutateAsync({ + orgId: currentOrg?.id, + authEnforced: value }); - - if (value) { - await logout.mutateAsync(); - - if (type === EnforceAuthType.SAML) { - window.open(`/api/v1/sso/redirect/saml2/organizations/${currentOrg.slug}`); - } else if (type === EnforceAuthType.GOOGLE) { - window.open(`/api/v1/sso/redirect/google?org_slug=${currentOrg.slug}`); - } - - window.close(); + } else if (type === EnforceAuthType.GOOGLE) { + if (!subscription?.enforceGoogleSSO) { + handlePopUpOpen("upgradePlan"); + return; } - } catch (err) { - console.error(err); + + await mutateAsync({ + orgId: currentOrg?.id, + googleSsoAuthEnforced: value + }); + } else if (type === EnforceAuthType.OIDC) { + if (!subscription?.oidcSSO) { + handlePopUpOpen("upgradePlan"); + return; + } + + await mutateAsync({ + orgId: currentOrg?.id, + authEnforced: value + }); + } else { createNotification({ - text: (err as { response: { data: { message: string } } }).response.data.message, + text: `Invalid auth enforcement type ${type}`, type: "error" }); } + + createNotification({ + text: `Successfully ${value ? "enabled" : "disabled"} org-level auth`, + type: "success" + }); + + if (value) { + await logout.mutateAsync(); + + if (type === EnforceAuthType.SAML) { + window.open(`/api/v1/sso/redirect/saml2/organizations/${currentOrg.slug}`); + } else if (type === EnforceAuthType.GOOGLE) { + window.open(`/api/v1/sso/redirect/google?org_slug=${currentOrg.slug}`); + } + + window.close(); + } }; const handleEnableBypassOrgAuthToggle = async (value: boolean) => { diff --git a/frontend/src/pages/organization/SettingsPage/components/OrgSsoTab/OrgLDAPSection.tsx b/frontend/src/pages/organization/SettingsPage/components/OrgSsoTab/OrgLDAPSection.tsx index 48625f218..311a7ea4b 100644 --- a/frontend/src/pages/organization/SettingsPage/components/OrgSsoTab/OrgLDAPSection.tsx +++ b/frontend/src/pages/organization/SettingsPage/components/OrgSsoTab/OrgLDAPSection.tsx @@ -31,31 +31,23 @@ export const OrgLDAPSection = (): JSX.Element => { const { mutateAsync: createMutateAsync } = useCreateLDAPConfig(); const handleLDAPToggle = async (value: boolean) => { - try { - if (!currentOrg?.id) return; - if (!subscription?.ldap) { - handlePopUpOpen("upgradePlan", { - isEnterpriseFeature: true - }); - return; - } - - await mutateAsync({ - organizationId: currentOrg?.id, - isActive: value - }); - - createNotification({ - text: `Successfully ${value ? "enabled" : "disabled"} LDAP`, - type: "success" - }); - } catch (err) { - console.error(err); - createNotification({ - text: `Failed to ${value ? "enable" : "disable"} LDAP`, - type: "error" + if (!currentOrg?.id) return; + if (!subscription?.ldap) { + handlePopUpOpen("upgradePlan", { + isEnterpriseFeature: true }); + return; } + + await mutateAsync({ + organizationId: currentOrg?.id, + isActive: value + }); + + createNotification({ + text: `Successfully ${value ? "enabled" : "disabled"} LDAP`, + type: "success" + }); }; const addLDAPBtnClick = async () => { diff --git a/frontend/src/pages/organization/SettingsPage/components/OrgSsoTab/OrgOIDCSection.tsx b/frontend/src/pages/organization/SettingsPage/components/OrgSsoTab/OrgOIDCSection.tsx index 3db364bc8..b722762e6 100644 --- a/frontend/src/pages/organization/SettingsPage/components/OrgSsoTab/OrgOIDCSection.tsx +++ b/frontend/src/pages/organization/SettingsPage/components/OrgSsoTab/OrgOIDCSection.tsx @@ -30,49 +30,41 @@ export const OrgOIDCSection = (): JSX.Element => { ] as const); const handleOIDCToggle = async (value: boolean) => { - try { - if (!currentOrg?.id) return; + if (!currentOrg?.id) return; - if (!subscription?.oidcSSO) { - handlePopUpOpen("upgradePlan"); - return; - } - - await mutateAsync({ - organizationId: currentOrg?.id, - isActive: value - }); - - createNotification({ - text: `Successfully ${value ? "enabled" : "disabled"} OIDC SSO`, - type: "success" - }); - } catch (err) { - console.error(err); + if (!subscription?.oidcSSO) { + handlePopUpOpen("upgradePlan"); + return; } + + await mutateAsync({ + organizationId: currentOrg?.id, + isActive: value + }); + + createNotification({ + text: `Successfully ${value ? "enabled" : "disabled"} OIDC SSO`, + type: "success" + }); }; const handleOIDCGroupManagement = async (value: boolean) => { - try { - if (!currentOrg?.id) return; + if (!currentOrg?.id) return; - if (!subscription?.oidcSSO) { - handlePopUpOpen("upgradePlan"); - return; - } - - await mutateAsync({ - organizationId: currentOrg?.id, - manageGroupMemberships: value - }); - - createNotification({ - text: `Successfully ${value ? "enabled" : "disabled"} OIDC group membership mapping`, - type: "success" - }); - } catch (err) { - console.error(err); + if (!subscription?.oidcSSO) { + handlePopUpOpen("upgradePlan"); + return; } + + await mutateAsync({ + organizationId: currentOrg?.id, + manageGroupMemberships: value + }); + + createNotification({ + text: `Successfully ${value ? "enabled" : "disabled"} OIDC group membership mapping`, + type: "success" + }); }; const addOidcButtonClick = async () => { diff --git a/frontend/src/pages/organization/SettingsPage/components/OrgSsoTab/OrgSSOSection.tsx b/frontend/src/pages/organization/SettingsPage/components/OrgSsoTab/OrgSSOSection.tsx index 343b549da..ba2d23abd 100644 --- a/frontend/src/pages/organization/SettingsPage/components/OrgSsoTab/OrgSSOSection.tsx +++ b/frontend/src/pages/organization/SettingsPage/components/OrgSsoTab/OrgSSOSection.tsx @@ -33,62 +33,46 @@ export const OrgSSOSection = (): JSX.Element => { const { mutateAsync: createMutateAsync } = useCreateSSOConfig(); const handleSamlSSOToggle = async (value: boolean) => { - try { - if (!currentOrg?.id) return; + if (!currentOrg?.id) return; - if (!subscription?.samlSSO) { - handlePopUpOpen("upgradePlan", { - text: "Your current plan does not include access to SAML SSO. To unlock this feature, please upgrade to Infisical Pro plan." - }); - return; - } - - await mutateAsync({ - organizationId: currentOrg?.id, - isActive: value - }); - - createNotification({ - text: `Successfully ${value ? "enabled" : "disabled"} SAML SSO`, - type: "success" - }); - } catch (err) { - console.error(err); - createNotification({ - text: `Failed to ${value ? "enable" : "disable"} SAML SSO`, - type: "error" + if (!subscription?.samlSSO) { + handlePopUpOpen("upgradePlan", { + text: "Your current plan does not include access to SAML SSO. To unlock this feature, please upgrade to Infisical Pro plan." }); + return; } + + await mutateAsync({ + organizationId: currentOrg?.id, + isActive: value + }); + + createNotification({ + text: `Successfully ${value ? "enabled" : "disabled"} SAML SSO`, + type: "success" + }); }; const handleSamlGroupManagement = async (value: boolean) => { - try { - if (!currentOrg?.id) return; + if (!currentOrg?.id) return; - if (!subscription?.samlSSO || !subscription?.groups) { - handlePopUpOpen("upgradePlan", { - isEnterpriseFeature: true, - text: "Your current plan does not include access to SAML group mapping. To unlock this feature, please upgrade to Infisical Enterprise plan." - }); - return; - } - - await mutateAsync({ - organizationId: currentOrg?.id, - enableGroupSync: value - }); - - createNotification({ - text: `Successfully ${value ? "enabled" : "disabled"} SAML group membership mapping`, - type: "success" - }); - } catch (err) { - console.error(err); - createNotification({ - text: `Failed to ${value ? "enable" : "disable"} SAML group membership mapping`, - type: "error" + if (!subscription?.samlSSO || !subscription?.groups) { + handlePopUpOpen("upgradePlan", { + isEnterpriseFeature: true, + text: "Your current plan does not include access to SAML group mapping. To unlock this feature, please upgrade to Infisical Enterprise plan." }); + return; } + + await mutateAsync({ + organizationId: currentOrg?.id, + enableGroupSync: value + }); + + createNotification({ + text: `Successfully ${value ? "enabled" : "disabled"} SAML group membership mapping`, + type: "success" + }); }; const addSSOBtnClick = async () => { diff --git a/frontend/src/pages/organization/SettingsPage/components/OrgSsoTab/SSOModal.tsx b/frontend/src/pages/organization/SettingsPage/components/OrgSsoTab/SSOModal.tsx index df5fca59f..558f37dcb 100644 --- a/frontend/src/pages/organization/SettingsPage/components/OrgSsoTab/SSOModal.tsx +++ b/frontend/src/pages/organization/SettingsPage/components/OrgSsoTab/SSOModal.tsx @@ -108,64 +108,49 @@ export const SSOModal = ({ popUp, handlePopUpClose, handlePopUpToggle, hideDelet if (!currentOrg) { return; } - try { - await updateMutateAsync({ - organizationId: currentOrg.id, - isActive: false, - entryPoint: "", - issuer: "", - cert: "" - }); + await updateMutateAsync({ + organizationId: currentOrg.id, + isActive: false, + entryPoint: "", + issuer: "", + cert: "" + }); - createNotification({ - text: "Successfully deleted SAML SSO configuration.", - type: "success" - }); - } catch { - createNotification({ - text: "Failed deleting SAML SSO configuration.", - type: "error" - }); - } + createNotification({ + text: "Successfully deleted SAML SSO configuration.", + type: "success" + }); }; const onSSOModalSubmit = async ({ authProvider, entryPoint, issuer, cert }: AddSSOFormData) => { - try { - if (!currentOrg) return; + if (!currentOrg) return; - if (!data) { - await createMutateAsync({ - organizationId: currentOrg.id, - authProvider, - isActive: false, - entryPoint, - issuer, - cert - }); - } else { - await updateMutateAsync({ - organizationId: currentOrg.id, - authProvider, - isActive: false, - entryPoint, - issuer, - cert - }); - } - - handlePopUpClose("addSSO"); - - createNotification({ - text: `Successfully ${!data ? "added" : "updated"} SAML SSO configuration`, - type: "success" + if (!data) { + await createMutateAsync({ + organizationId: currentOrg.id, + authProvider, + isActive: false, + entryPoint, + issuer, + cert }); - } catch (err) { - console.error(err); - createNotification({ - text: `Failed to ${!data ? "add" : "update"} SAML SSO configuration`, - type: "error" + } else { + await updateMutateAsync({ + organizationId: currentOrg.id, + authProvider, + isActive: false, + entryPoint, + issuer, + cert }); } + + handlePopUpClose("addSSO"); + + createNotification({ + text: `Successfully ${!data ? "added" : "updated"} SAML SSO configuration`, + type: "success" + }); }; const renderLabels = (authProvider: string) => { diff --git a/frontend/src/pages/organization/SettingsPage/components/ProjectTemplatesTab/components/DeleteProjectTemplateModal.tsx b/frontend/src/pages/organization/SettingsPage/components/ProjectTemplatesTab/components/DeleteProjectTemplateModal.tsx index 8ccdb0191..33b54afca 100644 --- a/frontend/src/pages/organization/SettingsPage/components/ProjectTemplatesTab/components/DeleteProjectTemplateModal.tsx +++ b/frontend/src/pages/organization/SettingsPage/components/ProjectTemplatesTab/components/DeleteProjectTemplateModal.tsx @@ -16,25 +16,16 @@ export const DeleteProjectTemplateModal = ({ isOpen, onOpenChange, template }: P const { id: templateId, name } = template; const handleDeleteProjectTemplate = async () => { - try { - await deleteTemplate.mutateAsync({ - templateId - }); + await deleteTemplate.mutateAsync({ + templateId + }); - createNotification({ - text: "Successfully removed project template", - type: "success" - }); + createNotification({ + text: "Successfully removed project template", + type: "success" + }); - onOpenChange(false); - } catch (err) { - console.error(err); - - createNotification({ - text: "Failed remove project template", - type: "error" - }); - } + onOpenChange(false); }; return ( diff --git a/frontend/src/pages/organization/SettingsPage/components/ProjectTemplatesTab/components/EditProjectTemplateSection/components/EditProjectTemplate.tsx b/frontend/src/pages/organization/SettingsPage/components/ProjectTemplatesTab/components/EditProjectTemplateSection/components/EditProjectTemplate.tsx index 7a99af1d6..afa8261b3 100644 --- a/frontend/src/pages/organization/SettingsPage/components/ProjectTemplatesTab/components/EditProjectTemplateSection/components/EditProjectTemplate.tsx +++ b/frontend/src/pages/organization/SettingsPage/components/ProjectTemplatesTab/components/EditProjectTemplateSection/components/EditProjectTemplate.tsx @@ -31,22 +31,14 @@ export const EditProjectTemplate = ({ isInfisicalTemplate, projectTemplate, onBa const deleteProjectTemplate = useDeleteProjectTemplate(); const handleRemoveTemplate = async () => { - try { - await deleteProjectTemplate.mutateAsync({ - templateId - }); - createNotification({ - text: "Successfully removed project template", - type: "success" - }); - onBack(); - } catch (error) { - console.error(error); - createNotification({ - text: "Failed to remove project template", - type: "error" - }); - } + await deleteProjectTemplate.mutateAsync({ + templateId + }); + createNotification({ + text: "Successfully removed project template", + type: "success" + }); + onBack(); handlePopUpClose("removeTemplate"); }; diff --git a/frontend/src/pages/organization/SettingsPage/components/ProjectTemplatesTab/components/EditProjectTemplateSection/components/ProjectTemplateEditRoleForm.tsx b/frontend/src/pages/organization/SettingsPage/components/ProjectTemplatesTab/components/EditProjectTemplateSection/components/ProjectTemplateEditRoleForm.tsx index 09a2a69af..e54eaf19d 100644 --- a/frontend/src/pages/organization/SettingsPage/components/ProjectTemplatesTab/components/EditProjectTemplateSection/components/ProjectTemplateEditRoleForm.tsx +++ b/frontend/src/pages/organization/SettingsPage/components/ProjectTemplatesTab/components/EditProjectTemplateSection/components/ProjectTemplateEditRoleForm.tsx @@ -57,31 +57,23 @@ export const ProjectTemplateEditRoleForm = ({ const updateProjectTemplate = useUpdateProjectTemplate(); const onSubmit = async (form: TFormSchema) => { - try { - await updateProjectTemplate.mutateAsync({ - templateId: projectTemplate.id, - roles: [ - ...projectTemplate.roles.filter( - (r) => r.slug !== role?.slug && isCustomProjectRole(r.slug) // filter out default roles as well - ), - { - ...form, - permissions: formRolePermission2API(form.permissions) - } - ] - }); - onGoBack(); - createNotification({ - text: "Template roles successfully updated", - type: "success" - }); - } catch (e: any) { - console.error(e); - createNotification({ - text: "Failed to update template roles", - type: "error" - }); - } + await updateProjectTemplate.mutateAsync({ + templateId: projectTemplate.id, + roles: [ + ...projectTemplate.roles.filter( + (r) => r.slug !== role?.slug && isCustomProjectRole(r.slug) // filter out default roles as well + ), + { + ...form, + permissions: formRolePermission2API(form.permissions) + } + ] + }); + onGoBack(); + createNotification({ + text: "Template roles successfully updated", + type: "success" + }); }; return ( diff --git a/frontend/src/pages/organization/SettingsPage/components/ProjectTemplatesTab/components/EditProjectTemplateSection/components/ProjectTemplateEnvironmentsForm.tsx b/frontend/src/pages/organization/SettingsPage/components/ProjectTemplatesTab/components/EditProjectTemplateSection/components/ProjectTemplateEnvironmentsForm.tsx index ec1899369..f11e9ecc8 100644 --- a/frontend/src/pages/organization/SettingsPage/components/ProjectTemplatesTab/components/EditProjectTemplateSection/components/ProjectTemplateEnvironmentsForm.tsx +++ b/frontend/src/pages/organization/SettingsPage/components/ProjectTemplatesTab/components/EditProjectTemplateSection/components/ProjectTemplateEnvironmentsForm.tsx @@ -68,28 +68,20 @@ export const ProjectTemplateEnvironmentsForm = ({ const updateProjectTemplate = useUpdateProjectTemplate(); const onFormSubmit = async (form: TFormSchema) => { - try { - const { environments: updatedEnvs } = await updateProjectTemplate.mutateAsync({ - environments: form.environments?.map((env, index) => ({ - ...env, - position: index + 1 - })), - templateId: projectTemplate.id - }); + const { environments: updatedEnvs } = await updateProjectTemplate.mutateAsync({ + environments: form.environments?.map((env, index) => ({ + ...env, + position: index + 1 + })), + templateId: projectTemplate.id + }); - reset({ environments: updatedEnvs }); + reset({ environments: updatedEnvs }); - createNotification({ - text: "Project template updated successfully", - type: "success" - }); - } catch (e: any) { - console.error(e); - createNotification({ - text: e.message ?? "Failed to update project template", - type: "error" - }); - } + createNotification({ + text: "Project template updated successfully", + type: "success" + }); }; const isEnvironmentLimitExceeded = diff --git a/frontend/src/pages/organization/SettingsPage/components/ProjectTemplatesTab/components/EditProjectTemplateSection/components/ProjectTemplateRolesSection.tsx b/frontend/src/pages/organization/SettingsPage/components/ProjectTemplatesTab/components/EditProjectTemplateSection/components/ProjectTemplateRolesSection.tsx index d65f7d785..cd5e41d2a 100644 --- a/frontend/src/pages/organization/SettingsPage/components/ProjectTemplatesTab/components/EditProjectTemplateSection/components/ProjectTemplateRolesSection.tsx +++ b/frontend/src/pages/organization/SettingsPage/components/ProjectTemplatesTab/components/EditProjectTemplateSection/components/ProjectTemplateRolesSection.tsx @@ -42,26 +42,18 @@ export const ProjectTemplateRolesSection = ({ projectTemplate, isInfisicalTempla const updateProjectTemplate = useUpdateProjectTemplate(); const handleRemoveRole = async (slug: string) => { - try { - await updateProjectTemplate.mutateAsync({ - templateId: projectTemplate.id, - roles: projectTemplate.roles.filter( - (role) => role.slug !== slug && isCustomProjectRole(role.slug) // filter out default roles as well - ) - }); + await updateProjectTemplate.mutateAsync({ + templateId: projectTemplate.id, + roles: projectTemplate.roles.filter( + (role) => role.slug !== slug && isCustomProjectRole(role.slug) // filter out default roles as well + ) + }); - createNotification({ - text: "Successfully removed role from template", - type: "success" - }); - handlePopUpClose("removeRole"); - } catch (e) { - console.error(e); - createNotification({ - text: "Error removing role from template", - type: "error" - }); - } + createNotification({ + text: "Successfully removed role from template", + type: "success" + }); + handlePopUpClose("removeRole"); }; const editRole = popUp?.editRole?.data as TProjectRole; diff --git a/frontend/src/pages/organization/SettingsPage/components/ProjectTemplatesTab/components/ProjectTemplateDetailsModal.tsx b/frontend/src/pages/organization/SettingsPage/components/ProjectTemplatesTab/components/ProjectTemplateDetailsModal.tsx index 6010d61f1..17224536d 100644 --- a/frontend/src/pages/organization/SettingsPage/components/ProjectTemplatesTab/components/ProjectTemplateDetailsModal.tsx +++ b/frontend/src/pages/organization/SettingsPage/components/ProjectTemplatesTab/components/ProjectTemplateDetailsModal.tsx @@ -93,25 +93,15 @@ const ProjectTemplateForm = ({ onComplete, projectTemplate }: FormProps) => { ? updateProjectTemplate.mutateAsync({ templateId: projectTemplate.id, ...data }) : createProjectTemplate.mutateAsync({ ...data }); - try { - const template = await mutation; - createNotification({ - text: `Successfully ${ - projectTemplate ? "updated template details" : "created project template" - }`, - type: "success" - }); + const template = await mutation; + createNotification({ + text: `Successfully ${ + projectTemplate ? "updated template details" : "created project template" + }`, + type: "success" + }); - onComplete(template); - } catch (err) { - console.error(err); - createNotification({ - text: `Failed to ${ - projectTemplate ? "update template details" : "create project template" - }`, - type: "error" - }); - } + onComplete(template); }; return ( diff --git a/frontend/src/pages/organization/UserDetailsByIDPage/UserDetailsByIDPage.tsx b/frontend/src/pages/organization/UserDetailsByIDPage/UserDetailsByIDPage.tsx index 47a607f4e..d607bc100 100644 --- a/frontend/src/pages/organization/UserDetailsByIDPage/UserDetailsByIDPage.tsx +++ b/frontend/src/pages/organization/UserDetailsByIDPage/UserDetailsByIDPage.tsx @@ -64,56 +64,38 @@ const Page = withPermission( ] as const); const onDeactivateMemberSubmit = async (orgMembershipId: string) => { - try { - await updateOrgMembership({ - organizationId: orgId, - membershipId: orgMembershipId, - isActive: false - }); + await updateOrgMembership({ + organizationId: orgId, + membershipId: orgMembershipId, + isActive: false + }); - createNotification({ - text: "Successfully deactivated user in organization", - type: "success" - }); - } catch (err) { - console.error(err); - createNotification({ - text: "Failed to deactivate user in organization", - type: "error" - }); - } + createNotification({ + text: "Successfully deactivated user in organization", + type: "success" + }); handlePopUpClose("deactivateMember"); }; const onRemoveMemberSubmit = async (orgMembershipId: string) => { - try { - await deleteOrgMembership({ - orgId, - membershipId: orgMembershipId - }); + await deleteOrgMembership({ + orgId, + membershipId: orgMembershipId + }); - createNotification({ - text: "Successfully removed user from org", - type: "success" - }); - - handlePopUpClose("removeMember"); - navigate({ - to: "/organization/access-management" as const, - search: { - selectedTab: OrgAccessControlTabSections.Member - } - }); - } catch (err) { - console.error(err); - createNotification({ - text: "Failed to remove user from the organization", - type: "error" - }); - } + createNotification({ + text: "Successfully removed user from org", + type: "success" + }); handlePopUpClose("removeMember"); + navigate({ + to: "/organization/access-management" as const, + search: { + selectedTab: OrgAccessControlTabSections.Member + } + }); }; return ( diff --git a/frontend/src/pages/organization/UserDetailsByIDPage/components/UserDetailsSection.tsx b/frontend/src/pages/organization/UserDetailsByIDPage/components/UserDetailsSection.tsx index bef98e875..d26163de0 100644 --- a/frontend/src/pages/organization/UserDetailsByIDPage/components/UserDetailsSection.tsx +++ b/frontend/src/pages/organization/UserDetailsByIDPage/components/UserDetailsSection.tsx @@ -46,26 +46,18 @@ export const UserDetailsSection = ({ membershipId, handlePopUpOpen }: Props) => const { mutateAsync: resendOrgMemberInvitation, isPending } = useResendOrgMemberInvitation(); const onResendInvite = async () => { - try { - const signupToken = await resendOrgMemberInvitation({ - membershipId - }); + const signupToken = await resendOrgMemberInvitation({ + membershipId + }); - if (signupToken) { - return; - } - - createNotification({ - text: "Successfully resent org invitation", - type: "success" - }); - } catch (err) { - console.error(err); - createNotification({ - text: "Failed to resend org invitation", - type: "error" - }); + if (signupToken) { + return; } + + createNotification({ + text: "Successfully resent org invitation", + type: "success" + }); }; const getStatus = (m: OrgUser) => { diff --git a/frontend/src/pages/organization/UserDetailsByIDPage/components/UserOrgMembershipModal.tsx b/frontend/src/pages/organization/UserDetailsByIDPage/components/UserOrgMembershipModal.tsx index 2518a5434..e8b976734 100644 --- a/frontend/src/pages/organization/UserDetailsByIDPage/components/UserOrgMembershipModal.tsx +++ b/frontend/src/pages/organization/UserDetailsByIDPage/components/UserOrgMembershipModal.tsx @@ -87,34 +87,23 @@ export const UserOrgMembershipModal = ({ popUp, handlePopUpOpen, handlePopUpTogg }, [popUp?.orgMembership?.data, roles]); const onFormSubmit = async ({ role, metadata }: FormData) => { - try { - if (!orgId) return; + if (!orgId) return; - await updateOrgMembership({ - organizationId: orgId, - membershipId: popUpData.membershipId, - role: role.slug, - metadata - }); + await updateOrgMembership({ + organizationId: orgId, + membershipId: popUpData.membershipId, + role: role.slug, + metadata + }); - handlePopUpToggle("orgMembership", false); + handlePopUpToggle("orgMembership", false); - createNotification({ - text: "Successfully updated user organization role", - type: "success" - }); + createNotification({ + text: "Successfully updated user organization role", + type: "success" + }); - reset(); - } catch (err) { - console.error(err); - const error = err as any; - const text = error?.response?.data?.message ?? "Failed to update user organization role"; - - createNotification({ - text, - type: "error" - }); - } + reset(); }; return ( diff --git a/frontend/src/pages/organization/UserDetailsByIDPage/components/UserProjectsSection/UserAddToProjectModal.tsx b/frontend/src/pages/organization/UserDetailsByIDPage/components/UserProjectsSection/UserAddToProjectModal.tsx index 572be1d81..013358c5f 100644 --- a/frontend/src/pages/organization/UserDetailsByIDPage/components/UserProjectsSection/UserAddToProjectModal.tsx +++ b/frontend/src/pages/organization/UserDetailsByIDPage/components/UserProjectsSection/UserAddToProjectModal.tsx @@ -67,30 +67,19 @@ const UserAddToProjectModalChild = ({ membershipId, popUp, handlePopUpToggle }: }, [workspaces, projectMemberships]); const onFormSubmit = async ({ projectId }: FormData) => { - try { - await addUserToWorkspaceNonE2EE({ - projectId, - usernames: [popupData.username], - orgId - }); + await addUserToWorkspaceNonE2EE({ + projectId, + usernames: [popupData.username], + orgId + }); - createNotification({ - text: "Successfully added user to project", - type: "success" - }); + createNotification({ + text: "Successfully added user to project", + type: "success" + }); - reset(); - handlePopUpToggle("addUserToProject", false); - } catch (err) { - console.error(err); - const error = err as any; - const text = error?.response?.data?.message ?? "Failed to add identity to project"; - - createNotification({ - text, - type: "error" - }); - } + reset(); + handlePopUpToggle("addUserToProject", false); }; return ( diff --git a/frontend/src/pages/organization/UserDetailsByIDPage/components/UserProjectsSection/UserGroupsSection.tsx b/frontend/src/pages/organization/UserDetailsByIDPage/components/UserProjectsSection/UserGroupsSection.tsx index 8e7cf3ce8..fafa7aff3 100644 --- a/frontend/src/pages/organization/UserDetailsByIDPage/components/UserProjectsSection/UserGroupsSection.tsx +++ b/frontend/src/pages/organization/UserDetailsByIDPage/components/UserProjectsSection/UserGroupsSection.tsx @@ -20,25 +20,18 @@ export const UserGroupsSection = ({ orgMembership }: Props) => { const { mutateAsync: removeUserFromGroup } = useRemoveUserFromGroup(); const handleRemoveUserFromGroup = useCallback(async (groupId: string, groupSlug: string) => { - try { - await removeUserFromGroup({ - groupId, - slug: groupSlug, - username: orgMembership.user.username - }); + await removeUserFromGroup({ + groupId, + slug: groupSlug, + username: orgMembership.user.username + }); - createNotification({ - type: "success", - text: "User removed from group successfully" - }); + createNotification({ + type: "success", + text: "User removed from group successfully" + }); - handlePopUpClose("removeUserFromGroup"); - } catch { - createNotification({ - type: "error", - text: "Failed to remove user from group" - }); - } + handlePopUpClose("removeUserFromGroup"); }, []); return ( diff --git a/frontend/src/pages/organization/UserDetailsByIDPage/components/UserProjectsSection/UserProjectsSection.tsx b/frontend/src/pages/organization/UserDetailsByIDPage/components/UserProjectsSection/UserProjectsSection.tsx index 843b5a63c..6e128036b 100644 --- a/frontend/src/pages/organization/UserDetailsByIDPage/components/UserProjectsSection/UserProjectsSection.tsx +++ b/frontend/src/pages/organization/UserDetailsByIDPage/components/UserProjectsSection/UserProjectsSection.tsx @@ -31,19 +31,11 @@ export const UserProjectsSection = ({ membershipId }: Props) => { ] as const); const handleRemoveUser = async (projectId: string, username: string) => { - try { - await removeUserFromWorkspace({ projectId, usernames: [username], orgId }); - createNotification({ - text: "Successfully removed user from project", - type: "success" - }); - } catch (error) { - console.error(error); - createNotification({ - text: "Failed to remove user from the project", - type: "error" - }); - } + await removeUserFromWorkspace({ projectId, usernames: [username], orgId }); + createNotification({ + text: "Successfully removed user from project", + type: "success" + }); handlePopUpClose("removeUserFromProject"); }; diff --git a/frontend/src/pages/pam/PamAccountsPage/components/PamAccountForm/PamAccountForm.tsx b/frontend/src/pages/pam/PamAccountsPage/components/PamAccountForm/PamAccountForm.tsx index b9599be2d..346195e11 100644 --- a/frontend/src/pages/pam/PamAccountsPage/components/PamAccountForm/PamAccountForm.tsx +++ b/frontend/src/pages/pam/PamAccountsPage/components/PamAccountForm/PamAccountForm.tsx @@ -38,27 +38,18 @@ const CreateForm = ({ const onSubmit = async ( formData: DiscriminativePick ) => { - try { - const account = await createPamAccount.mutateAsync({ - ...formData, - folderId, - resourceId, - resourceType, - projectId - }); - createNotification({ - text: "Successfully created account", - type: "success" - }); - onComplete(account); - } catch (err: any) { - console.error(err); - createNotification({ - title: "Failed to create account", - text: err.message, - type: "error" - }); - } + const account = await createPamAccount.mutateAsync({ + ...formData, + folderId, + resourceId, + resourceType, + projectId + }); + createNotification({ + text: "Successfully created account", + type: "success" + }); + onComplete(account); }; switch (resourceType) { @@ -85,25 +76,16 @@ const UpdateForm = ({ account, onComplete }: UpdateFormProps) => { const onSubmit = async ( formData: DiscriminativePick ) => { - try { - const updatedAccount = await updatePamAccount.mutateAsync({ - accountId: account.id, - resourceType: account.resource.resourceType, - ...formData - }); - createNotification({ - text: "Successfully updated account", - type: "success" - }); - onComplete(updatedAccount); - } catch (err: any) { - console.error(err); - createNotification({ - title: "Failed to update account", - text: err.message, - type: "error" - }); - } + const updatedAccount = await updatePamAccount.mutateAsync({ + accountId: account.id, + resourceType: account.resource.resourceType, + ...formData + }); + createNotification({ + text: "Successfully updated account", + type: "success" + }); + onComplete(updatedAccount); }; switch (account.resource.resourceType) { diff --git a/frontend/src/pages/pam/PamAccountsPage/components/PamAddFolderModal.tsx b/frontend/src/pages/pam/PamAccountsPage/components/PamAddFolderModal.tsx index 7b057a648..266a724cd 100644 --- a/frontend/src/pages/pam/PamAccountsPage/components/PamAddFolderModal.tsx +++ b/frontend/src/pages/pam/PamAccountsPage/components/PamAddFolderModal.tsx @@ -17,25 +17,16 @@ export const PamAddFolderModal = ({ isOpen, onOpenChange, projectId, currentFold console.log({ currentFolderId }); const onSubmit = async (formData: Pick) => { - try { - await createPamFolder.mutateAsync({ - ...formData, - parentId: currentFolderId, - projectId - }); - createNotification({ - text: "Successfully created folder", - type: "success" - }); - onOpenChange(false); - } catch (err: any) { - console.error(err); - createNotification({ - title: "Failed to create folder", - text: err.message, - type: "error" - }); - } + await createPamFolder.mutateAsync({ + ...formData, + parentId: currentFolderId, + projectId + }); + createNotification({ + text: "Successfully created folder", + type: "success" + }); + onOpenChange(false); }; return ( diff --git a/frontend/src/pages/pam/PamAccountsPage/components/PamDeleteAccountModal.tsx b/frontend/src/pages/pam/PamAccountsPage/components/PamDeleteAccountModal.tsx index 45ac03082..c094d3c53 100644 --- a/frontend/src/pages/pam/PamAccountsPage/components/PamDeleteAccountModal.tsx +++ b/frontend/src/pages/pam/PamAccountsPage/components/PamDeleteAccountModal.tsx @@ -20,25 +20,17 @@ export const PamDeleteAccountModal = ({ isOpen, onOpenChange, account }: Props) } = account; const handleDelete = async () => { - try { - await deletePamAccount.mutateAsync({ - accountId, - resourceType - }); + await deletePamAccount.mutateAsync({ + accountId, + resourceType + }); - createNotification({ - text: "Successfully deleted account", - type: "success" - }); + createNotification({ + text: "Successfully deleted account", + type: "success" + }); - onOpenChange(false); - } catch (err) { - console.error(err); - createNotification({ - text: "Failed to delete account", - type: "error" - }); - } + onOpenChange(false); }; return ( diff --git a/frontend/src/pages/pam/PamAccountsPage/components/PamDeleteFolderModal.tsx b/frontend/src/pages/pam/PamAccountsPage/components/PamDeleteFolderModal.tsx index f0e2476c2..d901d0ba0 100644 --- a/frontend/src/pages/pam/PamAccountsPage/components/PamDeleteFolderModal.tsx +++ b/frontend/src/pages/pam/PamAccountsPage/components/PamDeleteFolderModal.tsx @@ -16,24 +16,16 @@ export const PamDeleteFolderModal = ({ isOpen, onOpenChange, folder }: Props) => const { id: folderId, name } = folder; const handleDelete = async () => { - try { - await deletePamFolder.mutateAsync({ - folderId - }); + await deletePamFolder.mutateAsync({ + folderId + }); - createNotification({ - text: "Successfully deleted folder", - type: "success" - }); + createNotification({ + text: "Successfully deleted folder", + type: "success" + }); - onOpenChange(false); - } catch (err) { - console.error(err); - createNotification({ - text: "Failed to delete folder", - type: "error" - }); - } + onOpenChange(false); }; return ( diff --git a/frontend/src/pages/pam/PamAccountsPage/components/PamUpdateFolderModal.tsx b/frontend/src/pages/pam/PamAccountsPage/components/PamUpdateFolderModal.tsx index b4bcc46a4..4162ce25f 100644 --- a/frontend/src/pages/pam/PamAccountsPage/components/PamUpdateFolderModal.tsx +++ b/frontend/src/pages/pam/PamAccountsPage/components/PamUpdateFolderModal.tsx @@ -16,24 +16,15 @@ export const PamUpdateFolderModal = ({ isOpen, onOpenChange, folder }: Props) => if (!folder) return null; const onSubmit = async (formData: Pick) => { - try { - await updatePamFolder.mutateAsync({ - ...formData, - folderId: folder.id - }); - createNotification({ - text: "Successfully updated folder", - type: "success" - }); - onOpenChange(false); - } catch (err: any) { - console.error(err); - createNotification({ - title: "Failed to updated folder", - text: err.message, - type: "error" - }); - } + await updatePamFolder.mutateAsync({ + ...formData, + folderId: folder.id + }); + createNotification({ + text: "Successfully updated folder", + type: "success" + }); + onOpenChange(false); }; return ( diff --git a/frontend/src/pages/pam/PamResourcesPage/components/PamDeleteResourceModal.tsx b/frontend/src/pages/pam/PamResourcesPage/components/PamDeleteResourceModal.tsx index efda53466..7f0d2bd19 100644 --- a/frontend/src/pages/pam/PamResourcesPage/components/PamDeleteResourceModal.tsx +++ b/frontend/src/pages/pam/PamResourcesPage/components/PamDeleteResourceModal.tsx @@ -16,25 +16,17 @@ export const PamDeleteResourceModal = ({ isOpen, onOpenChange, resource }: Props const { id: resourceId, name, resourceType } = resource; const handleDelete = async () => { - try { - await deletePamResource.mutateAsync({ - resourceId, - resourceType - }); + await deletePamResource.mutateAsync({ + resourceId, + resourceType + }); - createNotification({ - text: `Successfully removed ${PAM_RESOURCE_TYPE_MAP[resourceType].name} resource`, - type: "success" - }); + createNotification({ + text: `Successfully removed ${PAM_RESOURCE_TYPE_MAP[resourceType].name} resource`, + type: "success" + }); - onOpenChange(false); - } catch (err) { - console.error(err); - createNotification({ - text: `Failed to remove ${PAM_RESOURCE_TYPE_MAP[resourceType].name} resource`, - type: "error" - }); - } + onOpenChange(false); }; return ( diff --git a/frontend/src/pages/pam/PamResourcesPage/components/PamResourceForm/PamResourceForm.tsx b/frontend/src/pages/pam/PamResourcesPage/components/PamResourceForm/PamResourceForm.tsx index 2bc54e7cd..3dd3aeec8 100644 --- a/frontend/src/pages/pam/PamResourcesPage/components/PamResourceForm/PamResourceForm.tsx +++ b/frontend/src/pages/pam/PamResourcesPage/components/PamResourceForm/PamResourceForm.tsx @@ -35,24 +35,15 @@ const CreateForm = ({ resourceType, onComplete, projectId }: CreateFormProps) => "name" | "resourceType" | "connectionDetails" | "gatewayId" > ) => { - try { - const resource = await createPamResource.mutateAsync({ - ...formData, - projectId - }); - createNotification({ - text: `Successfully created ${resourceName} resource`, - type: "success" - }); - onComplete(resource); - } catch (err: any) { - console.error(err); - createNotification({ - title: `Failed to create ${resourceName} resource`, - text: err.message, - type: "error" - }); - } + const resource = await createPamResource.mutateAsync({ + ...formData, + projectId + }); + createNotification({ + text: `Successfully created ${resourceName} resource`, + type: "success" + }); + onComplete(resource); }; switch (resourceType) { @@ -72,24 +63,15 @@ const UpdateForm = ({ resource, onComplete }: UpdateFormProps) => { const onSubmit = async ( formData: DiscriminativePick ) => { - try { - const updatedResource = await updatePamResource.mutateAsync({ - resourceId: resource.id, - ...formData - }); - createNotification({ - text: `Successfully updated ${resourceName} resource`, - type: "success" - }); - onComplete(updatedResource); - } catch (err: any) { - console.error(err); - createNotification({ - title: `Failed to update ${resourceName} resource`, - text: err.message, - type: "error" - }); - } + const updatedResource = await updatePamResource.mutateAsync({ + resourceId: resource.id, + ...formData + }); + createNotification({ + text: `Successfully updated ${resourceName} resource`, + type: "success" + }); + onComplete(updatedResource); }; switch (resource.resourceType) { diff --git a/frontend/src/pages/pam/PamSessionsByIDPage/components/PamSessionLogsSection.tsx b/frontend/src/pages/pam/PamSessionsByIDPage/components/PamSessionLogsSection.tsx index 5f06a64e2..7a4945540 100644 --- a/frontend/src/pages/pam/PamSessionsByIDPage/components/PamSessionLogsSection.tsx +++ b/frontend/src/pages/pam/PamSessionsByIDPage/components/PamSessionLogsSection.tsx @@ -1,42 +1,75 @@ -import { useState } from "react"; -import { faChevronDown, faChevronRight } from "@fortawesome/free-solid-svg-icons"; +import { useMemo, useState } from "react"; +import { faChevronRight, faMagnifyingGlass } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { twMerge } from "tailwind-merge"; +import { Input } from "@app/components/v2"; +import { HighlightText } from "@app/components/v2/HighlightText"; import { TPamSession } from "@app/hooks/api/pam"; +import { formatLogContent } from "./PamSessionLogsSection.utils"; + type Props = { session: TPamSession; }; export const PamSessionLogsSection = ({ session }: Props) => { const [expandedLogTimestamps, setExpandedLogTimestamps] = useState>(new Set()); + const [search, setSearch] = useState(""); const toggleExpand = (timestamp: string) => { setExpandedLogTimestamps((prev) => { - const newSet = new Set(prev); - if (newSet.has(timestamp)) { - newSet.delete(timestamp); - } else { - newSet.add(timestamp); + if (prev.has(timestamp)) { + return new Set(); } - return newSet; + return new Set([timestamp]); }); }; + const filteredLogs = useMemo( + () => + session.commandLogs.filter((log) => { + const { input, output } = log; + + const searchValue = search.trim().toLowerCase(); + + return ( + input.toLowerCase().includes(searchValue) || output.toLowerCase().includes(searchValue) + ); + }), + [session.commandLogs, search] + ); + return (

Session Logs

-
- {session.commandLogs.length > 0 ? ( - session.commandLogs.map((log) => { - const isExpanded = expandedLogTimestamps.has(log.timestamp); + +
+ { + const newSearch = e.target.value; + setSearch(newSearch); + }} + leftIcon={} + placeholder="Search logs..." + className="flex-1 bg-mineshaft-800" + containerClassName="bg-transparent" + /> +
+
+ {filteredLogs.length > 0 ? ( + filteredLogs.map((log) => { + const isExpanded = search.length || expandedLogTimestamps.has(log.timestamp); + const formattedInput = formatLogContent(log.input); + return ( ); }) ) : ( -
- {session.startedAt && session.endedAt ? ( +
+ {search.length ? ( +
+
No logs match search criteria
+
+ ) : (
Session logs are not yet available
@@ -78,8 +127,6 @@ export const PamSessionLogsSection = ({ session }: Props) => { If logs do not appear after some time, please contact your Gateway administrators.
- ) : ( - "No session logs" )}
)} diff --git a/frontend/src/pages/pam/PamSessionsByIDPage/components/PamSessionLogsSection.utils.ts b/frontend/src/pages/pam/PamSessionsByIDPage/components/PamSessionLogsSection.utils.ts new file mode 100644 index 000000000..d76145655 --- /dev/null +++ b/frontend/src/pages/pam/PamSessionsByIDPage/components/PamSessionLogsSection.utils.ts @@ -0,0 +1,46 @@ +// This function trims top and bottom empty padding, as well as moves all relative text to the left while still respecting indentation +export const formatLogContent = (text: string | null | undefined): string => { + if (!text) return ""; + + let lines = text.split("\n"); + + // Find the first and last non-empty lines to trim vertical padding + let firstLineIndex = -1; + for (let i = 0; i < lines.length; i += 1) { + if (lines[i].trim() !== "") { + firstLineIndex = i; + break; + } + } + + if (firstLineIndex === -1) { + return ""; + } + + let lastLineIndex = -1; + for (let i = lines.length - 1; i >= 0; i -= 1) { + if (lines[i].trim() !== "") { + lastLineIndex = i; + break; + } + } + + lines = lines.slice(firstLineIndex, lastLineIndex + 1); + + // Determine the minimum indentation of non-empty lines + const indentations = lines + .filter((line) => line.trim() !== "") + .map((line) => { + const match = line.match(/^\s*/); + return match ? match[0].length : 0; + }); + + const minIndentation = indentations.length > 0 ? Math.min(...indentations) : 0; + + // Remove the common indentation from all lines + if (minIndentation > 0) { + lines = lines.map((line) => line.substring(minIndentation)); + } + + return lines.join("\n"); +}; diff --git a/frontend/src/pages/pam/PamSessionsPage/components/PamSessionRow.tsx b/frontend/src/pages/pam/PamSessionsPage/components/PamSessionRow.tsx index f730e331d..8721560c4 100644 --- a/frontend/src/pages/pam/PamSessionsPage/components/PamSessionRow.tsx +++ b/frontend/src/pages/pam/PamSessionsPage/components/PamSessionRow.tsx @@ -27,6 +27,7 @@ import { HighlightText } from "@app/components/v2/HighlightText"; import { ProjectPermissionActions, ProjectPermissionSub } from "@app/context"; import { PAM_RESOURCE_TYPE_MAP, TPamSession } from "@app/hooks/api/pam"; +import { formatLogContent } from "../../PamSessionsByIDPage/components/PamSessionLogsSection.utils"; import { PamSessionStatusBadge } from "./PamSessionStatusBadge"; type Props = { @@ -159,21 +160,28 @@ export const PamSessionRow = ({ session, search, filteredCommandLogs }: Props) = {filteredCommandLogs.length > 0 && ( - {logsToShow.map((log) => ( -
-
- - {new Date(log.timestamp).toLocaleString()} -
+ {logsToShow.map((log) => { + const formattedInput = formatLogContent(log.input); -
- + return ( +
+
+ + {new Date(log.timestamp).toLocaleString()} +
+ +
+ +
+
+ +
-
- -
-
- ))} + ); + })} {filteredCommandLogs.length > LOGS_TO_SHOW && (
@@ -366,9 +364,8 @@ export const SecretApprovalRequestChangeItem = ({
Multi-line Encoding
{newVersion?.skipMultilineEncoding?.toString() ?? - secretVersion?.skipMultilineEncoding?.toString() ?? ( - - - )}{" "} + secretVersion?.skipMultilineEncoding?.toString() ?? + "false"}
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 24d306314..bd4a04fa3 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 @@ -174,23 +174,15 @@ export const SecretApprovalRequestChanges = ({ approvalRequestId, onGoBack }: Pr ); const handleSecretApprovalStatusUpdate = async (status: ApprovalStatus, comment: string) => { - try { - await updateSecretApprovalRequestStatus({ - id: approvalRequestId, - status, - comment - }); - createNotification({ - type: "success", - text: `Successfully ${status} the request` - }); - } catch (err) { - console.log(err); - createNotification({ - type: "error", - text: "Failed to update the request status" - }); - } + await updateSecretApprovalRequestStatus({ + id: approvalRequestId, + status, + comment + }); + createNotification({ + type: "success", + text: `Successfully ${status} the request` + }); handlePopUpToggle("reviewChanges", false); reset({ diff --git a/frontend/src/pages/secret-manager/SecretDashboardPage/SecretDashboardPage.tsx b/frontend/src/pages/secret-manager/SecretDashboardPage/SecretDashboardPage.tsx index f1a7ffba8..a2ee814f8 100644 --- a/frontend/src/pages/secret-manager/SecretDashboardPage/SecretDashboardPage.tsx +++ b/frontend/src/pages/secret-manager/SecretDashboardPage/SecretDashboardPage.tsx @@ -338,45 +338,37 @@ const Page = () => { const isProtectedBranch = Boolean(boardPolicy); const handleCreateCommit = async (changes: PendingChanges, message: string) => { - try { - await createCommit({ - projectId, - environment, - secretPath, - pendingChanges: changes, - message - }); + await createCommit({ + projectId, + environment, + secretPath, + pendingChanges: changes, + message + }); - if (!isProtectedBranch) { - pendingChanges.secrets.forEach((secret) => { - if (secret.type === "update" && secret.secretValue !== undefined) { - queryClient.setQueryData( - dashboardKeys.getSecretValue({ - projectId, - environment, - secretPath, - secretKey: secret.newSecretName ?? secret.secretKey, - isOverride: false - }), - { value: secret.secretValue } - ); - } - }); - } - - createNotification({ - text: isProtectedBranch - ? "Requested changes have been sent for review" - : "Changes saved successfully", - type: "success" + if (!isProtectedBranch) { + pendingChanges.secrets.forEach((secret) => { + if (secret.type === "update" && secret.secretValue !== undefined) { + queryClient.setQueryData( + dashboardKeys.getSecretValue({ + projectId, + environment, + secretPath, + secretKey: secret.newSecretName ?? secret.secretKey, + isOverride: false + }), + { value: secret.secretValue } + ); + } }); - } catch (error) { - createNotification({ - text: "Failed to save changes", - type: "error" - }); - console.error(error); } + + createNotification({ + text: isProtectedBranch + ? "Requested changes have been sent for review" + : "Changes saved successfully", + type: "success" + }); }; const { diff --git a/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/ActionBar.tsx b/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/ActionBar.tsx index c3fb5159b..727903999 100644 --- a/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/ActionBar.tsx +++ b/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/ActionBar.tsx @@ -209,48 +209,40 @@ export const ActionBar = ({ const isOrgAdmin = hasOrgRole(OrgMembershipRole.Admin); const handleFolderCreate = async (folderName: string, description: string | null) => { - try { - if (isBatchMode) { - const folderId = `${folderName}`; - const pendingFolderCreate: PendingFolderCreate = { - id: folderId, - resourceType: "folder", - type: PendingAction.Create, - folderName, - description: description || undefined, - parentPath: secretPath, - timestamp: Date.now() - }; + if (isBatchMode) { + const folderId = `${folderName}`; + const pendingFolderCreate: PendingFolderCreate = { + id: folderId, + resourceType: "folder", + type: PendingAction.Create, + folderName, + description: description || undefined, + parentPath: secretPath, + timestamp: Date.now() + }; - addPendingChange(pendingFolderCreate, { - projectId, - environment, - secretPath - }); - - handlePopUpClose("addFolder"); - return; - } - - await createFolder({ - name: folderName, - path: secretPath, - environment, + addPendingChange(pendingFolderCreate, { projectId, - description + environment, + secretPath }); + handlePopUpClose("addFolder"); - createNotification({ - type: "success", - text: "Successfully created folder" - }); - } catch (error) { - console.log(error); - createNotification({ - type: "error", - text: "Failed to create folder" - }); + return; } + + await createFolder({ + name: folderName, + path: secretPath, + environment, + projectId, + description + }); + handlePopUpClose("addFolder"); + createNotification({ + type: "success", + text: "Successfully created folder" + }); }; const handleSecretDownload = async () => { @@ -323,26 +315,18 @@ export const ActionBar = ({ const handleSecretBulkDelete = async () => { const bulkDeletedSecrets = Object.values(selectedSecrets); - try { - await deleteBatchSecretV3({ - secretPath, - projectId, - environment, - secrets: bulkDeletedSecrets.map(({ key }) => ({ secretKey: key, type: SecretType.Shared })) - }); - resetSelectedSecret(); - handlePopUpClose("bulkDeleteSecrets"); - createNotification({ - type: "success", - text: "Successfully deleted secrets" - }); - } catch (error) { - console.log(error); - createNotification({ - type: "error", - text: "Failed to delete secrets" - }); - } + await deleteBatchSecretV3({ + secretPath, + projectId, + environment, + secrets: bulkDeletedSecrets.map(({ key }) => ({ secretKey: key, type: SecretType.Shared })) + }); + resetSelectedSecret(); + handlePopUpClose("bulkDeleteSecrets"); + createNotification({ + type: "success", + text: "Successfully deleted secrets" + }); }; const handleSecretsMove = async ({ @@ -678,35 +662,23 @@ export const ActionBar = ({ }; const handleVaultImport = async (vaultPath: string, namespace: string) => { - try { - const result = await importVaultSecrets({ - projectId, - environment, - secretPath, - vaultNamespace: namespace, - vaultSecretPath: vaultPath - }); - - if (result.status === VaultImportStatus.ApprovalRequired) { - createNotification({ - type: "info", - text: "Secret change request created successfully. Awaiting approval." - }); - } else { - createNotification({ - type: "success", - text: "Successfully imported secrets from HashiCorp Vault" - }); - } - } catch (err) { - console.error("Vault import error:", err); - const error = err as AxiosError<{ message?: string }>; - const errorMessage = - error.response?.data?.message || "Failed to import secrets from Vault. Please try again."; + const result = await importVaultSecrets({ + projectId, + environment, + secretPath, + vaultNamespace: namespace, + vaultSecretPath: vaultPath + }); + if (result.status === VaultImportStatus.ApprovalRequired) { createNotification({ - type: "error", - text: errorMessage + type: "info", + text: "Secret change request created successfully. Awaiting approval." + }); + } else { + createNotification({ + type: "success", + text: "Successfully imported secrets from HashiCorp Vault" }); } }; diff --git a/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/AwsElastiCacheInputForm.tsx b/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/AwsElastiCacheInputForm.tsx index c58f2a754..48bd2012b 100644 --- a/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/AwsElastiCacheInputForm.tsx +++ b/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/AwsElastiCacheInputForm.tsx @@ -4,7 +4,6 @@ import ms from "ms"; import { z } from "zod"; import { TtlFormLabel } from "@app/components/features"; -import { createNotification } from "@app/components/notifications"; import { Accordion, AccordionContent, @@ -111,25 +110,18 @@ export const AwsElastiCacheInputForm = ({ if (createDynamicSecret.isPending) return; const isDefaultUsernameTemplate = usernameTemplate === "{{randomUsername}}"; - try { - await createDynamicSecret.mutateAsync({ - provider: { type: DynamicSecretProviders.AwsElastiCache, inputs: provider }, - maxTTL, - name, - path: secretPath, - defaultTTL, - projectSlug, - environmentSlug: environment.slug, - usernameTemplate: - !usernameTemplate || isDefaultUsernameTemplate ? undefined : usernameTemplate - }); - onCompleted(); - } catch { - createNotification({ - type: "error", - text: "Failed to create dynamic secret" - }); - } + await createDynamicSecret.mutateAsync({ + provider: { type: DynamicSecretProviders.AwsElastiCache, inputs: provider }, + maxTTL, + name, + path: secretPath, + defaultTTL, + projectSlug, + environmentSlug: environment.slug, + usernameTemplate: + !usernameTemplate || isDefaultUsernameTemplate ? undefined : usernameTemplate + }); + onCompleted(); }; return ( diff --git a/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/AwsIamInputForm.tsx b/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/AwsIamInputForm.tsx index 35a416224..e4438d117 100644 --- a/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/AwsIamInputForm.tsx +++ b/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/AwsIamInputForm.tsx @@ -4,7 +4,6 @@ import ms from "ms"; import { z } from "zod"; import { TtlFormLabel } from "@app/components/features"; -import { createNotification } from "@app/components/notifications"; import { Button, FilterableSelect, @@ -166,26 +165,19 @@ export const AwsIamInputForm = ({ // wait till previous request is finished if (createDynamicSecret.isPending) return; - try { - const isDefaultUsernameTemplate = usernameTemplate === "{{randomUsername}}"; - await createDynamicSecret.mutateAsync({ - provider: { type: DynamicSecretProviders.AwsIam, inputs: provider }, - maxTTL, - name, - path: secretPath, - defaultTTL, - projectSlug, - environmentSlug: environment.slug, - usernameTemplate: - !usernameTemplate || isDefaultUsernameTemplate ? undefined : usernameTemplate - }); - onCompleted(); - } catch { - createNotification({ - type: "error", - text: "Failed to create dynamic secret" - }); - } + const isDefaultUsernameTemplate = usernameTemplate === "{{randomUsername}}"; + await createDynamicSecret.mutateAsync({ + provider: { type: DynamicSecretProviders.AwsIam, inputs: provider }, + maxTTL, + name, + path: secretPath, + defaultTTL, + projectSlug, + environmentSlug: environment.slug, + usernameTemplate: + !usernameTemplate || isDefaultUsernameTemplate ? undefined : usernameTemplate + }); + onCompleted(); }; return ( diff --git a/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/AzureEntraIdInputForm.tsx b/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/AzureEntraIdInputForm.tsx index 581c473b9..b4506c51a 100644 --- a/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/AzureEntraIdInputForm.tsx +++ b/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/AzureEntraIdInputForm.tsx @@ -6,7 +6,6 @@ import ms from "ms"; import { z } from "zod"; import { TtlFormLabel } from "@app/components/features"; -import { createNotification } from "@app/components/notifications"; import { Button, FilterableSelect, FormControl, Input } from "@app/components/v2"; import { DropdownMenu, @@ -112,34 +111,27 @@ export const AzureEntraIdInputForm = ({ }: TForm) => { // wait till previous request is finished if (createDynamicSecret.isPending) return; - try { - selectedUsers.map(async (user: { id: string; name: string; email: string }) => { - await createDynamicSecret.mutateAsync({ - provider: { - type: DynamicSecretProviders.AzureEntraId, - inputs: { - userId: user.id, - tenantId: provider.tenantId, - email: user.email, - applicationId: provider.applicationId, - clientSecret: provider.clientSecret - } - }, - maxTTL, - name: `${name}-${user.name}`, - path: secretPath, - defaultTTL, - projectSlug, - environmentSlug: environment.slug - }); + selectedUsers.map(async (user: { id: string; name: string; email: string }) => { + await createDynamicSecret.mutateAsync({ + provider: { + type: DynamicSecretProviders.AzureEntraId, + inputs: { + userId: user.id, + tenantId: provider.tenantId, + email: user.email, + applicationId: provider.applicationId, + clientSecret: provider.clientSecret + } + }, + maxTTL, + name: `${name}-${user.name}`, + path: secretPath, + defaultTTL, + projectSlug, + environmentSlug: environment.slug }); - onCompleted(); - } catch { - createNotification({ - type: "error", - text: "Failed to create dynamic secret" - }); - } + }); + onCompleted(); }; return ( diff --git a/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/AzureSqlDatabaseInputForm.tsx b/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/AzureSqlDatabaseInputForm.tsx index aece11f38..954aed3ba 100644 --- a/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/AzureSqlDatabaseInputForm.tsx +++ b/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/AzureSqlDatabaseInputForm.tsx @@ -5,7 +5,6 @@ import ms from "ms"; import { z } from "zod"; import { TtlFormLabel } from "@app/components/features"; -import { createNotification } from "@app/components/notifications"; import { OrgPermissionCan } from "@app/components/permissions"; import { Accordion, @@ -171,29 +170,22 @@ export const AzureSqlDatabaseInputForm = ({ if (createDynamicSecret.isPending) return; const isDefaultUsernameTemplate = usernameTemplate === "{{randomUsername}}"; - try { - await createDynamicSecret.mutateAsync({ - provider: { - type: DynamicSecretProviders.AzureSqlDatabase, - inputs: { ...provider, masterDatabase: "master" } - }, - maxTTL, - name, - path: secretPath, - defaultTTL, - projectSlug, - environmentSlug: environment.slug, - metadata, - usernameTemplate: - !usernameTemplate || isDefaultUsernameTemplate ? undefined : usernameTemplate - }); - onCompleted(); - } catch { - createNotification({ - type: "error", - text: "Failed to create dynamic secret" - }); - } + await createDynamicSecret.mutateAsync({ + provider: { + type: DynamicSecretProviders.AzureSqlDatabase, + inputs: { ...provider, masterDatabase: "master" } + }, + maxTTL, + name, + path: secretPath, + defaultTTL, + projectSlug, + environmentSlug: environment.slug, + metadata, + usernameTemplate: + !usernameTemplate || isDefaultUsernameTemplate ? undefined : usernameTemplate + }); + onCompleted(); }; return ( diff --git a/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/CassandraInputForm.tsx b/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/CassandraInputForm.tsx index 15f9387df..dd0c3e879 100644 --- a/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/CassandraInputForm.tsx +++ b/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/CassandraInputForm.tsx @@ -4,7 +4,6 @@ import ms from "ms"; import { z } from "zod"; import { TtlFormLabel } from "@app/components/features"; -import { createNotification } from "@app/components/notifications"; import { Accordion, AccordionContent, @@ -112,25 +111,18 @@ export const CassandraInputForm = ({ if (createDynamicSecret.isPending) return; const isDefaultUsernameTemplate = usernameTemplate === "{{randomUsername}}"; - try { - await createDynamicSecret.mutateAsync({ - provider: { type: DynamicSecretProviders.Cassandra, inputs: provider }, - maxTTL, - name, - path: secretPath, - defaultTTL, - projectSlug, - environmentSlug: environment.slug, - usernameTemplate: - !usernameTemplate || isDefaultUsernameTemplate ? undefined : usernameTemplate - }); - onCompleted(); - } catch { - createNotification({ - type: "error", - text: "Failed to create dynamic secret" - }); - } + await createDynamicSecret.mutateAsync({ + provider: { type: DynamicSecretProviders.Cassandra, inputs: provider }, + maxTTL, + name, + path: secretPath, + defaultTTL, + projectSlug, + environmentSlug: environment.slug, + usernameTemplate: + !usernameTemplate || isDefaultUsernameTemplate ? undefined : usernameTemplate + }); + onCompleted(); }; return ( diff --git a/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/CouchbaseInputForm.tsx b/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/CouchbaseInputForm.tsx index 17bfeddca..894b31c1c 100644 --- a/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/CouchbaseInputForm.tsx +++ b/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/CouchbaseInputForm.tsx @@ -7,7 +7,6 @@ import ms from "ms"; import { z } from "zod"; import { TtlFormLabel } from "@app/components/features"; -import { createNotification } from "@app/components/notifications"; import { Accordion, AccordionContent, @@ -386,25 +385,18 @@ export const CouchbaseInputForm = ({ const { useAdvancedBuckets, ...finalProvider } = transformedProvider; - try { - await createDynamicSecret.mutateAsync({ - provider: { type: DynamicSecretProviders.Couchbase, inputs: finalProvider }, - maxTTL, - name, - path: secretPath, - defaultTTL, - projectSlug, - environmentSlug: environment.slug, - usernameTemplate: - !usernameTemplate || isDefaultUsernameTemplate ? undefined : usernameTemplate - }); - onCompleted(); - } catch { - createNotification({ - type: "error", - text: "Failed to create dynamic secret" - }); - } + await createDynamicSecret.mutateAsync({ + provider: { type: DynamicSecretProviders.Couchbase, inputs: finalProvider }, + maxTTL, + name, + path: secretPath, + defaultTTL, + projectSlug, + environmentSlug: environment.slug, + usernameTemplate: + !usernameTemplate || isDefaultUsernameTemplate ? undefined : usernameTemplate + }); + onCompleted(); }; return ( diff --git a/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/ElasticSearchInputForm.tsx b/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/ElasticSearchInputForm.tsx index 1d0b6c268..d6477862b 100644 --- a/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/ElasticSearchInputForm.tsx +++ b/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/ElasticSearchInputForm.tsx @@ -6,7 +6,6 @@ import ms from "ms"; import { z } from "zod"; import { TtlFormLabel } from "@app/components/features"; -import { createNotification } from "@app/components/notifications"; import { Button, FilterableSelect, @@ -131,25 +130,18 @@ export const ElasticSearchInputForm = ({ // wait till previous request is finished if (createDynamicSecret.isPending) return; const isDefaultUsernameTemplate = usernameTemplate === "{{randomUsername}}"; - try { - await createDynamicSecret.mutateAsync({ - provider: { type: DynamicSecretProviders.ElasticSearch, inputs: provider }, - maxTTL, - name, - path: secretPath, - defaultTTL, - projectSlug, - environmentSlug: environment.slug, - usernameTemplate: - !usernameTemplate || isDefaultUsernameTemplate ? undefined : usernameTemplate - }); - onCompleted(); - } catch { - createNotification({ - type: "error", - text: "Failed to create dynamic secret" - }); - } + await createDynamicSecret.mutateAsync({ + provider: { type: DynamicSecretProviders.ElasticSearch, inputs: provider }, + maxTTL, + name, + path: secretPath, + defaultTTL, + projectSlug, + environmentSlug: environment.slug, + usernameTemplate: + !usernameTemplate || isDefaultUsernameTemplate ? undefined : usernameTemplate + }); + onCompleted(); }; const selectedAuthType = watch("provider.auth.type"); diff --git a/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/GcpIamInputForm.tsx b/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/GcpIamInputForm.tsx index a208b1973..a0134bfde 100644 --- a/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/GcpIamInputForm.tsx +++ b/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/GcpIamInputForm.tsx @@ -4,7 +4,6 @@ import ms from "ms"; import { z } from "zod"; import { TtlFormLabel } from "@app/components/features"; -import { createNotification } from "@app/components/notifications"; import { Button, FilterableSelect, FormControl, Input } from "@app/components/v2"; import { useCreateDynamicSecret } from "@app/hooks/api"; import { DynamicSecretProviders } from "@app/hooks/api/dynamicSecret/types"; @@ -83,28 +82,21 @@ export const GcpIamInputForm = ({ }: TForm) => { // wait till previous request is finished if (createDynamicSecret.isPending) return; - try { - await createDynamicSecret.mutateAsync({ - provider: { - type: DynamicSecretProviders.GcpIam, - inputs: { - ...provider - } - }, - maxTTL, - name, - path: secretPath, - defaultTTL, - projectSlug, - environmentSlug: environment.slug - }); - onCompleted(); - } catch { - createNotification({ - type: "error", - text: "Failed to create dynamic secret" - }); - } + await createDynamicSecret.mutateAsync({ + provider: { + type: DynamicSecretProviders.GcpIam, + inputs: { + ...provider + } + }, + maxTTL, + name, + path: secretPath, + defaultTTL, + projectSlug, + environmentSlug: environment.slug + }); + onCompleted(); }; return ( diff --git a/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/GithubInputForm.tsx b/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/GithubInputForm.tsx index 776511ac4..31256f5a1 100644 --- a/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/GithubInputForm.tsx +++ b/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/GithubInputForm.tsx @@ -4,7 +4,6 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { zodResolver } from "@hookform/resolvers/zod"; import { z } from "zod"; -import { createNotification } from "@app/components/notifications"; import { Button, FilterableSelect, @@ -71,27 +70,20 @@ export const GithubInputForm = ({ const handleCreateDynamicSecret = async ({ name, provider, environment }: TForm) => { if (createDynamicSecret.isPending) return; - try { - await createDynamicSecret.mutateAsync({ - provider: { - type: DynamicSecretProviders.Github, - inputs: { - ...provider - } - }, - defaultTTL: "1h", // Github is limited to 1 hour tokens - name, - path: secretPath, - projectSlug, - environmentSlug: environment.slug - }); - onCompleted(); - } catch { - createNotification({ - type: "error", - text: "Failed to create dynamic secret" - }); - } + await createDynamicSecret.mutateAsync({ + provider: { + type: DynamicSecretProviders.Github, + inputs: { + ...provider + } + }, + defaultTTL: "1h", // Github is limited to 1 hour tokens + name, + path: secretPath, + projectSlug, + environmentSlug: environment.slug + }); + onCompleted(); }; return ( diff --git a/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/KubernetesInputForm.tsx b/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/KubernetesInputForm.tsx index d15bcc9b8..a439f1af2 100644 --- a/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/KubernetesInputForm.tsx +++ b/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/KubernetesInputForm.tsx @@ -283,33 +283,26 @@ export const KubernetesInputForm = ({ // wait till previous request is finished if (createDynamicSecret.isPending) return; - try { - const isDefaultUsernameTemplate = usernameTemplate === "{{randomUsername}}"; - await createDynamicSecret.mutateAsync({ - provider: { - type: DynamicSecretProviders.Kubernetes, - inputs: { - ...provider, - url: provider.url || undefined - } - }, - maxTTL: rest.maxTTL, - name: rest.name, - path: secretPath, - defaultTTL: rest.defaultTTL, - projectSlug, - environmentSlug: rest.environment.slug, - usernameTemplate: - !usernameTemplate || isDefaultUsernameTemplate ? undefined : usernameTemplate - }); + const isDefaultUsernameTemplate = usernameTemplate === "{{randomUsername}}"; + await createDynamicSecret.mutateAsync({ + provider: { + type: DynamicSecretProviders.Kubernetes, + inputs: { + ...provider, + url: provider.url || undefined + } + }, + maxTTL: rest.maxTTL, + name: rest.name, + path: secretPath, + defaultTTL: rest.defaultTTL, + projectSlug, + environmentSlug: rest.environment.slug, + usernameTemplate: + !usernameTemplate || isDefaultUsernameTemplate ? undefined : usernameTemplate + }); - onCompleted(); - } catch { - createNotification({ - type: "error", - text: "Failed to create dynamic secret" - }); - } + onCompleted(); }; return ( diff --git a/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/LdapInputForm.tsx b/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/LdapInputForm.tsx index 7b7397625..61273fc41 100644 --- a/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/LdapInputForm.tsx +++ b/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/LdapInputForm.tsx @@ -4,7 +4,6 @@ import ms from "ms"; import { z } from "zod"; import { TtlFormLabel } from "@app/components/features"; -import { createNotification } from "@app/components/notifications"; import { Button, FilterableSelect, @@ -139,25 +138,18 @@ export const LdapInputForm = ({ if (createDynamicSecret.isPending) return; const isDefaultUsernameTemplate = usernameTemplate === "{{randomUsername}}"; - try { - await createDynamicSecret.mutateAsync({ - provider: { type: DynamicSecretProviders.Ldap, inputs: provider }, - maxTTL, - name, - path: secretPath, - defaultTTL, - projectSlug, - usernameTemplate: - !usernameTemplate || isDefaultUsernameTemplate ? undefined : usernameTemplate, - environmentSlug: environment.slug - }); - onCompleted(); - } catch { - createNotification({ - type: "error", - text: "Failed to create dynamic secret" - }); - } + await createDynamicSecret.mutateAsync({ + provider: { type: DynamicSecretProviders.Ldap, inputs: provider }, + maxTTL, + name, + path: secretPath, + defaultTTL, + projectSlug, + usernameTemplate: + !usernameTemplate || isDefaultUsernameTemplate ? undefined : usernameTemplate, + environmentSlug: environment.slug + }); + onCompleted(); }; return ( diff --git a/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/MongoAtlasInputForm.tsx b/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/MongoAtlasInputForm.tsx index 3b0c7bb3b..317febae8 100644 --- a/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/MongoAtlasInputForm.tsx +++ b/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/MongoAtlasInputForm.tsx @@ -6,7 +6,6 @@ import ms from "ms"; import { z } from "zod"; import { TtlFormLabel } from "@app/components/features"; -import { createNotification } from "@app/components/notifications"; import { Accordion, AccordionContent, @@ -143,25 +142,18 @@ export const MongoAtlasInputForm = ({ if (createDynamicSecret.isPending) return; const isDefaultUsernameTemplate = usernameTemplate === "{{randomUsername}}"; - try { - await createDynamicSecret.mutateAsync({ - provider: { type: DynamicSecretProviders.MongoAtlas, inputs: provider }, - maxTTL, - name, - path: secretPath, - defaultTTL, - projectSlug, - environmentSlug: environment.slug, - usernameTemplate: - !usernameTemplate || isDefaultUsernameTemplate ? undefined : usernameTemplate - }); - onCompleted(); - } catch { - createNotification({ - type: "error", - text: "Failed to create dynamic secret" - }); - } + await createDynamicSecret.mutateAsync({ + provider: { type: DynamicSecretProviders.MongoAtlas, inputs: provider }, + maxTTL, + name, + path: secretPath, + defaultTTL, + projectSlug, + environmentSlug: environment.slug, + usernameTemplate: + !usernameTemplate || isDefaultUsernameTemplate ? undefined : usernameTemplate + }); + onCompleted(); }; return ( diff --git a/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/MongoDBInputForm.tsx b/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/MongoDBInputForm.tsx index ac60a77b0..8099b123c 100644 --- a/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/MongoDBInputForm.tsx +++ b/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/MongoDBInputForm.tsx @@ -6,7 +6,6 @@ import ms from "ms"; import { z } from "zod"; import { TtlFormLabel } from "@app/components/features"; -import { createNotification } from "@app/components/notifications"; import { Button, FilterableSelect, @@ -113,32 +112,25 @@ export const MongoDBDatabaseInputForm = ({ if (createDynamicSecret.isPending) return; const isDefaultUsernameTemplate = usernameTemplate === "{{randomUsername}}"; - try { - await createDynamicSecret.mutateAsync({ - provider: { - type: DynamicSecretProviders.MongoDB, - inputs: { - ...provider, - port: provider?.port ? provider.port : undefined, - roles: provider.roles.map((el) => el.roleName) - } - }, - maxTTL, - name, - path: secretPath, - defaultTTL, - projectSlug, - environmentSlug: environment.slug, - usernameTemplate: - !usernameTemplate || isDefaultUsernameTemplate ? undefined : usernameTemplate - }); - onCompleted(); - } catch { - createNotification({ - type: "error", - text: "Failed to create dynamic secret" - }); - } + await createDynamicSecret.mutateAsync({ + provider: { + type: DynamicSecretProviders.MongoDB, + inputs: { + ...provider, + port: provider?.port ? provider.port : undefined, + roles: provider.roles.map((el) => el.roleName) + } + }, + maxTTL, + name, + path: secretPath, + defaultTTL, + projectSlug, + environmentSlug: environment.slug, + usernameTemplate: + !usernameTemplate || isDefaultUsernameTemplate ? undefined : usernameTemplate + }); + onCompleted(); }; return ( diff --git a/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/RabbitMqInputForm.tsx b/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/RabbitMqInputForm.tsx index 7b2e56464..b142682dd 100644 --- a/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/RabbitMqInputForm.tsx +++ b/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/RabbitMqInputForm.tsx @@ -6,7 +6,6 @@ import ms from "ms"; import { z } from "zod"; import { TtlFormLabel } from "@app/components/features"; -import { createNotification } from "@app/components/notifications"; import { Button, FilterableSelect, @@ -121,25 +120,18 @@ export const RabbitMqInputForm = ({ if (createDynamicSecret.isPending) return; const isDefaultUsernameTemplate = usernameTemplate === "{{randomUsername}}"; - try { - await createDynamicSecret.mutateAsync({ - provider: { type: DynamicSecretProviders.RabbitMq, inputs: provider }, - maxTTL, - name, - path: secretPath, - defaultTTL, - projectSlug, - environmentSlug: environment.slug, - usernameTemplate: - !usernameTemplate || isDefaultUsernameTemplate ? undefined : usernameTemplate - }); - onCompleted(); - } catch { - createNotification({ - type: "error", - text: "Failed to create dynamic secret" - }); - } + await createDynamicSecret.mutateAsync({ + provider: { type: DynamicSecretProviders.RabbitMq, inputs: provider }, + maxTTL, + name, + path: secretPath, + defaultTTL, + projectSlug, + environmentSlug: environment.slug, + usernameTemplate: + !usernameTemplate || isDefaultUsernameTemplate ? undefined : usernameTemplate + }); + onCompleted(); }; const selectedTags = watch("provider.tags"); diff --git a/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/RedisInputForm.tsx b/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/RedisInputForm.tsx index 472d30783..31745ae79 100644 --- a/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/RedisInputForm.tsx +++ b/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/RedisInputForm.tsx @@ -4,7 +4,6 @@ import ms from "ms"; import { z } from "zod"; import { TtlFormLabel } from "@app/components/features"; -import { createNotification } from "@app/components/notifications"; import { Accordion, AccordionContent, @@ -104,26 +103,19 @@ export const RedisInputForm = ({ }: TForm) => { // wait till previous request is finished if (createDynamicSecret.isPending) return; - try { - const isDefaultUsernameTemplate = usernameTemplate === "{{randomUsername}}"; - await createDynamicSecret.mutateAsync({ - provider: { type: DynamicSecretProviders.Redis, inputs: provider }, - maxTTL, - name, - path: secretPath, - defaultTTL, - projectSlug, - environmentSlug: environment.slug, - usernameTemplate: - !usernameTemplate || isDefaultUsernameTemplate ? undefined : usernameTemplate - }); - onCompleted(); - } catch { - createNotification({ - type: "error", - text: "Failed to create dynamic secret" - }); - } + const isDefaultUsernameTemplate = usernameTemplate === "{{randomUsername}}"; + await createDynamicSecret.mutateAsync({ + provider: { type: DynamicSecretProviders.Redis, inputs: provider }, + maxTTL, + name, + path: secretPath, + defaultTTL, + projectSlug, + environmentSlug: environment.slug, + usernameTemplate: + !usernameTemplate || isDefaultUsernameTemplate ? undefined : usernameTemplate + }); + onCompleted(); }; return ( diff --git a/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/SapAseInputForm.tsx b/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/SapAseInputForm.tsx index 621451fda..42c06ebea 100644 --- a/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/SapAseInputForm.tsx +++ b/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/SapAseInputForm.tsx @@ -4,7 +4,6 @@ import ms from "ms"; import { z } from "zod"; import { TtlFormLabel } from "@app/components/features"; -import { createNotification } from "@app/components/notifications"; import { Accordion, AccordionContent, @@ -105,26 +104,19 @@ sp_droplogin '{{username}}';` }: TForm) => { // wait till previous request is finished if (createDynamicSecret.isPending) return; - try { - const isDefaultUsernameTemplate = usernameTemplate === "{{randomUsername}}"; - await createDynamicSecret.mutateAsync({ - provider: { type: DynamicSecretProviders.SapAse, inputs: provider }, - maxTTL, - name, - path: secretPath, - defaultTTL, - projectSlug, - environmentSlug: environment.slug, - usernameTemplate: - !usernameTemplate || isDefaultUsernameTemplate ? undefined : usernameTemplate - }); - onCompleted(); - } catch { - createNotification({ - type: "error", - text: "Failed to create dynamic secret" - }); - } + const isDefaultUsernameTemplate = usernameTemplate === "{{randomUsername}}"; + await createDynamicSecret.mutateAsync({ + provider: { type: DynamicSecretProviders.SapAse, inputs: provider }, + maxTTL, + name, + path: secretPath, + defaultTTL, + projectSlug, + environmentSlug: environment.slug, + usernameTemplate: + !usernameTemplate || isDefaultUsernameTemplate ? undefined : usernameTemplate + }); + onCompleted(); }; return ( diff --git a/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/SapHanaInputForm.tsx b/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/SapHanaInputForm.tsx index 034afee2c..8984d1f49 100644 --- a/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/SapHanaInputForm.tsx +++ b/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/SapHanaInputForm.tsx @@ -4,7 +4,6 @@ import ms from "ms"; import { z } from "zod"; import { TtlFormLabel } from "@app/components/features"; -import { createNotification } from "@app/components/notifications"; import { Accordion, AccordionContent, @@ -105,26 +104,19 @@ DROP USER {{username}};`, }: TForm) => { // wait till previous request is finished if (createDynamicSecret.isPending) return; - try { - const isDefaultUsernameTemplate = usernameTemplate === "{{randomUsername}}"; - await createDynamicSecret.mutateAsync({ - provider: { type: DynamicSecretProviders.SapHana, inputs: provider }, - maxTTL, - name, - path: secretPath, - defaultTTL, - projectSlug, - usernameTemplate: - !usernameTemplate || isDefaultUsernameTemplate ? undefined : usernameTemplate, - environmentSlug: environment.slug - }); - onCompleted(); - } catch { - createNotification({ - type: "error", - text: "Failed to create dynamic secret" - }); - } + const isDefaultUsernameTemplate = usernameTemplate === "{{randomUsername}}"; + await createDynamicSecret.mutateAsync({ + provider: { type: DynamicSecretProviders.SapHana, inputs: provider }, + maxTTL, + name, + path: secretPath, + defaultTTL, + projectSlug, + usernameTemplate: + !usernameTemplate || isDefaultUsernameTemplate ? undefined : usernameTemplate, + environmentSlug: environment.slug + }); + onCompleted(); }; return ( diff --git a/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/SnowflakeInputForm.tsx b/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/SnowflakeInputForm.tsx index 11357e26a..91f638f39 100644 --- a/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/SnowflakeInputForm.tsx +++ b/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/SnowflakeInputForm.tsx @@ -4,7 +4,6 @@ import ms from "ms"; import { z } from "zod"; import { TtlFormLabel } from "@app/components/features"; -import { createNotification } from "@app/components/notifications"; import { Accordion, AccordionContent, @@ -102,26 +101,19 @@ export const SnowflakeInputForm = ({ }: TForm) => { // wait till previous request is finished if (createDynamicSecret.isPending) return; - try { - const isDefaultUsernameTemplate = usernameTemplate === "{{randomUsername}}"; - await createDynamicSecret.mutateAsync({ - provider: { type: DynamicSecretProviders.Snowflake, inputs: provider }, - maxTTL, - name, - path: secretPath, - defaultTTL, - projectSlug, - environmentSlug: environment.slug, - usernameTemplate: - !usernameTemplate || isDefaultUsernameTemplate ? undefined : usernameTemplate - }); - onCompleted(); - } catch (err) { - createNotification({ - type: "error", - text: err instanceof Error ? err.message : "Failed to create dynamic secret" - }); - } + const isDefaultUsernameTemplate = usernameTemplate === "{{randomUsername}}"; + await createDynamicSecret.mutateAsync({ + provider: { type: DynamicSecretProviders.Snowflake, inputs: provider }, + maxTTL, + name, + path: secretPath, + defaultTTL, + projectSlug, + environmentSlug: environment.slug, + usernameTemplate: + !usernameTemplate || isDefaultUsernameTemplate ? undefined : usernameTemplate + }); + onCompleted(); }; return ( diff --git a/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/SqlDatabaseInputForm.tsx b/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/SqlDatabaseInputForm.tsx index 0a836fec2..aaf2e43d1 100644 --- a/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/SqlDatabaseInputForm.tsx +++ b/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/SqlDatabaseInputForm.tsx @@ -5,7 +5,6 @@ import ms from "ms"; import { z } from "zod"; import { TtlFormLabel } from "@app/components/features"; -import { createNotification } from "@app/components/notifications"; import { OrgPermissionCan } from "@app/components/permissions"; import { Accordion, @@ -215,26 +214,19 @@ export const SqlDatabaseInputForm = ({ if (createDynamicSecret.isPending) return; const isDefaultUsernameTemplate = usernameTemplate === "{{randomUsername}}"; - try { - await createDynamicSecret.mutateAsync({ - provider: { type: DynamicSecretProviders.SqlDatabase, inputs: provider }, - maxTTL, - name, - path: secretPath, - defaultTTL, - projectSlug, - environmentSlug: environment.slug, - metadata, - usernameTemplate: - !usernameTemplate || isDefaultUsernameTemplate ? undefined : usernameTemplate - }); - onCompleted(); - } catch { - createNotification({ - type: "error", - text: "Failed to create dynamic secret" - }); - } + await createDynamicSecret.mutateAsync({ + provider: { type: DynamicSecretProviders.SqlDatabase, inputs: provider }, + maxTTL, + name, + path: secretPath, + defaultTTL, + projectSlug, + environmentSlug: environment.slug, + metadata, + usernameTemplate: + !usernameTemplate || isDefaultUsernameTemplate ? undefined : usernameTemplate + }); + onCompleted(); }; const handleDatabaseChange = (type: SqlProviders) => { diff --git a/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/TotpInputForm.tsx b/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/TotpInputForm.tsx index 7f5693e33..f86ac4017 100644 --- a/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/TotpInputForm.tsx +++ b/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/TotpInputForm.tsx @@ -2,7 +2,6 @@ import { Controller, useForm } from "react-hook-form"; import { zodResolver } from "@hookform/resolvers/zod"; import { z } from "zod"; -import { createNotification } from "@app/components/notifications"; import { Button, FilterableSelect, @@ -100,23 +99,16 @@ export const TotpInputForm = ({ const handleCreateDynamicSecret = async ({ name, provider, environment }: TForm) => { // wait till previous request is finished if (createDynamicSecret.isPending) return; - try { - await createDynamicSecret.mutateAsync({ - provider: { type: DynamicSecretProviders.Totp, inputs: provider }, - maxTTL: "24h", - name, - path: secretPath, - defaultTTL: "1m", - projectSlug, - environmentSlug: environment.slug - }); - onCompleted(); - } catch (err) { - createNotification({ - type: "error", - text: err instanceof Error ? err.message : "Failed to create dynamic secret" - }); - } + await createDynamicSecret.mutateAsync({ + provider: { type: DynamicSecretProviders.Totp, inputs: provider }, + maxTTL: "24h", + name, + path: secretPath, + defaultTTL: "1m", + projectSlug, + environmentSlug: environment.slug + }); + onCompleted(); }; return ( diff --git a/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/VerticaInputForm.tsx b/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/VerticaInputForm.tsx index b48eab850..7bd66a466 100644 --- a/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/VerticaInputForm.tsx +++ b/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateDynamicSecretForm/VerticaInputForm.tsx @@ -5,7 +5,6 @@ import ms from "ms"; import { z } from "zod"; import { TtlFormLabel } from "@app/components/features"; -import { createNotification } from "@app/components/notifications"; import { OrgPermissionCan } from "@app/components/permissions"; import { Accordion, @@ -145,26 +144,19 @@ GRANT CREATE ON SCHEMA public TO {{username}};`, usernameTemplate }: TForm) => { if (createDynamicSecret.isPending) return; - try { - const isDefaultUsernameTemplate = usernameTemplate === "{{randomUsername}}"; - await createDynamicSecret.mutateAsync({ - provider: { type: DynamicSecretProviders.Vertica, inputs: provider }, - maxTTL, - name, - path: secretPath, - defaultTTL, - projectSlug, - environmentSlug: environment.slug, - usernameTemplate: - !usernameTemplate || isDefaultUsernameTemplate ? undefined : usernameTemplate - }); - onCompleted(); - } catch { - createNotification({ - type: "error", - text: "Failed to create dynamic secret" - }); - } + const isDefaultUsernameTemplate = usernameTemplate === "{{randomUsername}}"; + await createDynamicSecret.mutateAsync({ + provider: { type: DynamicSecretProviders.Vertica, inputs: provider }, + maxTTL, + name, + path: secretPath, + defaultTTL, + projectSlug, + environmentSlug: environment.slug, + usernameTemplate: + !usernameTemplate || isDefaultUsernameTemplate ? undefined : usernameTemplate + }); + onCompleted(); }; return ( diff --git a/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateSecretImportForm.tsx b/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateSecretImportForm.tsx index 68d2d8cd0..73a9d938e 100644 --- a/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateSecretImportForm.tsx +++ b/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/CreateSecretImportForm.tsx @@ -101,11 +101,6 @@ export const CreateSecretImportForm = ({ text: "You do not have access to the selected environment/path", type: "error" }); - } else { - createNotification({ - type: "error", - text: "Failed to link secrets" - }); } } }; diff --git a/frontend/src/pages/secret-manager/SecretDashboardPage/components/CreateSecretForm/CreateSecretForm.tsx b/frontend/src/pages/secret-manager/SecretDashboardPage/components/CreateSecretForm/CreateSecretForm.tsx index dd0561495..858fcde77 100644 --- a/frontend/src/pages/secret-manager/SecretDashboardPage/components/CreateSecretForm/CreateSecretForm.tsx +++ b/frontend/src/pages/secret-manager/SecretDashboardPage/components/CreateSecretForm/CreateSecretForm.tsx @@ -77,70 +77,55 @@ export const CreateSecretForm = ({ const slugSchema = z.string().trim().toLowerCase().min(1); const createNewTag = async (slug: string) => { // TODO: Replace with slugSchema generic - try { - const parsedSlug = slugSchema.parse(slug); - await createWsTag.mutateAsync({ - projectId, - tagSlug: parsedSlug, - tagColor: "" - }); - } catch { - createNotification({ - type: "error", - text: "Failed to create new tag" - }); - } + const parsedSlug = slugSchema.parse(slug); + await createWsTag.mutateAsync({ + projectId, + tagSlug: parsedSlug, + tagColor: "" + }); }; const handleFormSubmit = async ({ key, value, tags }: TFormSchema) => { - try { - if (isBatchMode) { - const pendingSecretCreate: PendingSecretCreate = { - id: key, - type: PendingAction.Create, - secretKey: key, - secretValue: value || "", - secretComment: "", - tags: tags?.map((el) => ({ id: el.value, slug: el.label })), - timestamp: Date.now(), - resourceType: "secret" - }; - addPendingChange(pendingSecretCreate, { - projectId, - - environment, - secretPath - }); - closePopUp(PopUpNames.CreateSecretForm); - reset(); - return; - } - await createSecretV3({ - environment, - projectId, - secretPath, + if (isBatchMode) { + const pendingSecretCreate: PendingSecretCreate = { + id: key, + type: PendingAction.Create, secretKey: key, secretValue: value || "", secretComment: "", - type: SecretType.Shared, - tagIds: tags?.map((el) => el.value) + tags: tags?.map((el) => ({ id: el.value, slug: el.label })), + timestamp: Date.now(), + resourceType: "secret" + }; + addPendingChange(pendingSecretCreate, { + projectId, + + environment, + secretPath }); closePopUp(PopUpNames.CreateSecretForm); reset(); - - createNotification({ - type: isProtectedBranch ? "info" : "success", - text: isProtectedBranch - ? "Requested changes have been sent for review" - : "Successfully created secret" - }); - } catch (error) { - console.log(error); - createNotification({ - type: "error", - text: "Failed to create secret" - }); + return; } + await createSecretV3({ + environment, + projectId, + secretPath, + secretKey: key, + secretValue: value || "", + secretComment: "", + type: SecretType.Shared, + tagIds: tags?.map((el) => el.value) + }); + closePopUp(PopUpNames.CreateSecretForm); + reset(); + + createNotification({ + type: isProtectedBranch ? "info" : "success", + text: isProtectedBranch + ? "Requested changes have been sent for review" + : "Successfully created secret" + }); }; const handlePaste = (e: ClipboardEvent) => { diff --git a/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/CreateDynamicSecretLease.tsx b/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/CreateDynamicSecretLease.tsx index 1a16e6e4e..99e66e8b7 100644 --- a/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/CreateDynamicSecretLease.tsx +++ b/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/CreateDynamicSecretLease.tsx @@ -441,30 +441,22 @@ export const CreateKubernetesDynamicSecretLease = ({ const handleDynamicSecretLeaseCreate = async ({ ttl, namespace }: TKubernetesForm) => { if (createDynamicSecretLease.isPending) return; - try { - await createDynamicSecretLease.mutateAsync({ - environmentSlug: environment, - projectSlug, - path: secretPath, - ttl, - dynamicSecretName, - config: { - namespace: namespace || undefined - }, - provider - }); + await createDynamicSecretLease.mutateAsync({ + environmentSlug: environment, + projectSlug, + path: secretPath, + ttl, + dynamicSecretName, + config: { + namespace: namespace || undefined + }, + provider + }); - createNotification({ - type: "success", - text: "Successfully leased dynamic secret" - }); - } catch (error) { - console.log(error); - createNotification({ - type: "error", - text: "Failed to lease dynamic secret" - }); - } + createNotification({ + type: "success", + text: "Successfully leased dynamic secret" + }); }; const handleLeaseRegeneration = async (data: { ttl?: string }) => { @@ -590,29 +582,21 @@ export const CreateDynamicSecretLease = ({ const handleDynamicSecretLeaseCreate = async ({ ttl }: TForm) => { if (createDynamicSecretLease.isPending) return; - try { - await createDynamicSecretLease.mutateAsync({ - environmentSlug: environment, - projectSlug, - path: secretPath, - ttl, - dynamicSecretName, - provider - }); + await createDynamicSecretLease.mutateAsync({ + environmentSlug: environment, + projectSlug, + path: secretPath, + ttl, + dynamicSecretName, + provider + }); - createNotification({ - type: "success", - text: "Successfully leased dynamic secret" - }); + createNotification({ + type: "success", + text: "Successfully leased dynamic secret" + }); - setIsPreloading.off(); - } catch (error) { - console.log(error); - createNotification({ - type: "error", - text: "Failed to lease dynamic secret" - }); - } + setIsPreloading.off(); }; const handleLeaseRegeneration = async (data: { ttl?: string }) => { diff --git a/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/DynamicSecretLease.tsx b/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/DynamicSecretLease.tsx index 085a06169..1f734de32 100644 --- a/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/DynamicSecretLease.tsx +++ b/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/DynamicSecretLease.tsx @@ -69,31 +69,23 @@ export const DynamicSecretLease = ({ const deleteDynamicSecretLease = useRevokeDynamicSecretLease(); const handleDynamicSecretDeleteLease = async () => { - try { - const { leaseId, isForced } = popUp.deleteSecret.data as { - leaseId: string; - isForced?: boolean; - }; - await deleteDynamicSecretLease.mutateAsync({ - environmentSlug: environment, - projectSlug, - path: secretPath, - dynamicSecretName, - leaseId, - isForced - }); - handlePopUpClose("deleteSecret"); - createNotification({ - type: "success", - text: "Successfully deleted lease" - }); - } catch (error) { - console.log(error); - createNotification({ - type: "error", - text: "Failed to delete lease" - }); - } + const { leaseId, isForced } = popUp.deleteSecret.data as { + leaseId: string; + isForced?: boolean; + }; + await deleteDynamicSecretLease.mutateAsync({ + environmentSlug: environment, + projectSlug, + path: secretPath, + dynamicSecretName, + leaseId, + isForced + }); + handlePopUpClose("deleteSecret"); + createNotification({ + type: "success", + text: "Successfully deleted lease" + }); }; const canRenew = !DYNAMIC_SECRETS_WITHOUT_RENEWAL.includes(dynamicSecret.type); diff --git a/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/DynamicSecretListView.tsx b/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/DynamicSecretListView.tsx index 1ef140193..d444f8390 100644 --- a/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/DynamicSecretListView.tsx +++ b/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/DynamicSecretListView.tsx @@ -54,29 +54,21 @@ export const DynamicSecretListView = ({ const deleteDynamicSecret = useDeleteDynamicSecret(); const handleDynamicSecretDelete = async () => { - try { - const { name, isForced } = popUp.deleteDynamicSecret.data as TDynamicSecret & { - isForced?: boolean; - }; - await deleteDynamicSecret.mutateAsync({ - environmentSlug: environment, - projectSlug, - path: secretPath, - name, - isForced - }); - handlePopUpClose("deleteDynamicSecret"); - createNotification({ - type: "success", - text: "Successfully deleted dynamic secret" - }); - } catch (error) { - console.log(error); - createNotification({ - type: "error", - text: "Failed to delete dynamic secret" - }); - } + const { name, isForced } = popUp.deleteDynamicSecret.data as TDynamicSecret & { + isForced?: boolean; + }; + await deleteDynamicSecret.mutateAsync({ + environmentSlug: environment, + projectSlug, + path: secretPath, + name, + isForced + }); + handlePopUpClose("deleteDynamicSecret"); + createNotification({ + type: "success", + text: "Successfully deleted dynamic secret" + }); }; return ( diff --git a/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretAwsElastiCacheProviderForm.tsx b/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretAwsElastiCacheProviderForm.tsx index 5740e2061..0015c0c0c 100644 --- a/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretAwsElastiCacheProviderForm.tsx +++ b/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretAwsElastiCacheProviderForm.tsx @@ -101,31 +101,24 @@ export const EditDynamicSecretAwsElastiCacheProviderForm = ({ // wait till previous request is finished if (updateDynamicSecret.isPending) return; const isDefaultUsernameTemplate = usernameTemplate === "{{randomUsername}}"; - try { - await updateDynamicSecret.mutateAsync({ - name: dynamicSecret.name, - path: secretPath, - projectSlug, - environmentSlug: environment, - data: { - maxTTL: maxTTL || undefined, - defaultTTL, - inputs, - newName: newName === dynamicSecret.name ? undefined : newName, - usernameTemplate: !usernameTemplate || isDefaultUsernameTemplate ? null : usernameTemplate - } - }); - onClose(); - createNotification({ - type: "success", - text: "Successfully updated dynamic secret" - }); - } catch { - createNotification({ - type: "error", - text: "Failed to update dynamic secret" - }); - } + await updateDynamicSecret.mutateAsync({ + name: dynamicSecret.name, + path: secretPath, + projectSlug, + environmentSlug: environment, + data: { + maxTTL: maxTTL || undefined, + defaultTTL, + inputs, + newName: newName === dynamicSecret.name ? undefined : newName, + usernameTemplate: !usernameTemplate || isDefaultUsernameTemplate ? null : usernameTemplate + } + }); + onClose(); + createNotification({ + type: "success", + text: "Successfully updated dynamic secret" + }); }; return ( diff --git a/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretAwsIamForm.tsx b/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretAwsIamForm.tsx index 555ed9eae..c9c9afb71 100644 --- a/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretAwsIamForm.tsx +++ b/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretAwsIamForm.tsx @@ -141,31 +141,24 @@ export const EditDynamicSecretAwsIamForm = ({ // wait till previous request is finished if (updateDynamicSecret.isPending) return; const isDefaultUsernameTemplate = usernameTemplate === "{{randomUsername}}"; - try { - await updateDynamicSecret.mutateAsync({ - name: dynamicSecret.name, - path: secretPath, - projectSlug, - environmentSlug: environment, - data: { - maxTTL: maxTTL || undefined, - defaultTTL, - inputs, - newName: newName === dynamicSecret.name ? undefined : newName, - usernameTemplate: !usernameTemplate || isDefaultUsernameTemplate ? null : usernameTemplate - } - }); - onClose(); - createNotification({ - type: "success", - text: "Successfully updated dynamic secret" - }); - } catch { - createNotification({ - type: "error", - text: "Failed to update dynamic secret" - }); - } + await updateDynamicSecret.mutateAsync({ + name: dynamicSecret.name, + path: secretPath, + projectSlug, + environmentSlug: environment, + data: { + maxTTL: maxTTL || undefined, + defaultTTL, + inputs, + newName: newName === dynamicSecret.name ? undefined : newName, + usernameTemplate: !usernameTemplate || isDefaultUsernameTemplate ? null : usernameTemplate + } + }); + onClose(); + createNotification({ + type: "success", + text: "Successfully updated dynamic secret" + }); }; return ( diff --git a/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretAzureEntraIdForm.tsx b/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretAzureEntraIdForm.tsx index c9bfc92cc..2799a95ed 100644 --- a/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretAzureEntraIdForm.tsx +++ b/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretAzureEntraIdForm.tsx @@ -76,30 +76,23 @@ export const EditDynamicSecretAzureEntraIdForm = ({ const handleUpdateDynamicSecret = async ({ maxTTL, defaultTTL, newName, inputs }: TForm) => { // wait till previous request is finished if (updateDynamicSecret.isPending) return; - try { - await updateDynamicSecret.mutateAsync({ - name: dynamicSecret.name, - path: secretPath, - projectSlug, - environmentSlug: environment, - data: { - maxTTL: maxTTL || undefined, - defaultTTL, - newName: newName === dynamicSecret.name ? undefined : newName, - inputs - } - }); - onClose(); - createNotification({ - type: "success", - text: "Successfully updated dynamic secret" - }); - } catch { - createNotification({ - type: "error", - text: "Failed to update dynamic secret" - }); - } + await updateDynamicSecret.mutateAsync({ + name: dynamicSecret.name, + path: secretPath, + projectSlug, + environmentSlug: environment, + data: { + maxTTL: maxTTL || undefined, + defaultTTL, + newName: newName === dynamicSecret.name ? undefined : newName, + inputs + } + }); + onClose(); + createNotification({ + type: "success", + text: "Successfully updated dynamic secret" + }); }; return ( diff --git a/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretAzureSqlDatabaseForm.tsx b/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretAzureSqlDatabaseForm.tsx index 77bb7aa1f..fd370d755 100644 --- a/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretAzureSqlDatabaseForm.tsx +++ b/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretAzureSqlDatabaseForm.tsx @@ -162,33 +162,26 @@ export const EditDynamicSecretAzureSqlDatabaseForm = ({ }: TForm) => { if (updateDynamicSecret.isPending) return; - try { - const isDefaultUsernameTemplate = usernameTemplate === "{{randomUsername}}"; - await updateDynamicSecret.mutateAsync({ - projectSlug, - environmentSlug: environment, - path: secretPath, - name: dynamicSecret.name, - data: { - maxTTL: maxTTL || undefined, - defaultTTL, - inputs: inputs ? { ...inputs, masterDatabase: "master" } : undefined, - newName: newName === dynamicSecret.name ? undefined : newName, - metadata, - usernameTemplate: !usernameTemplate || isDefaultUsernameTemplate ? null : usernameTemplate - } - }); - onClose(); - createNotification({ - type: "success", - text: "Successfully updated dynamic secret" - }); - } catch { - createNotification({ - type: "error", - text: "Failed to update dynamic secret" - }); - } + const isDefaultUsernameTemplate = usernameTemplate === "{{randomUsername}}"; + await updateDynamicSecret.mutateAsync({ + projectSlug, + environmentSlug: environment, + path: secretPath, + name: dynamicSecret.name, + data: { + maxTTL: maxTTL || undefined, + defaultTTL, + inputs: inputs ? { ...inputs, masterDatabase: "master" } : undefined, + newName: newName === dynamicSecret.name ? undefined : newName, + metadata, + usernameTemplate: !usernameTemplate || isDefaultUsernameTemplate ? null : usernameTemplate + } + }); + onClose(); + createNotification({ + type: "success", + text: "Successfully updated dynamic secret" + }); }; return ( diff --git a/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretCassandraForm.tsx b/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretCassandraForm.tsx index 515ee19e3..fe1212330 100644 --- a/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretCassandraForm.tsx +++ b/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretCassandraForm.tsx @@ -103,31 +103,24 @@ export const EditDynamicSecretCassandraForm = ({ // wait till previous request is finished if (updateDynamicSecret.isPending) return; const isDefaultUsernameTemplate = usernameTemplate === "{{randomUsername}}"; - try { - await updateDynamicSecret.mutateAsync({ - name: dynamicSecret.name, - path: secretPath, - projectSlug, - environmentSlug: environment, - data: { - maxTTL: maxTTL || undefined, - defaultTTL, - inputs, - newName: newName === dynamicSecret.name ? undefined : newName, - usernameTemplate: !usernameTemplate || isDefaultUsernameTemplate ? null : usernameTemplate - } - }); - onClose(); - createNotification({ - type: "success", - text: "Successfully updated dynamic secret" - }); - } catch { - createNotification({ - type: "error", - text: "Failed to update dynamic secret" - }); - } + await updateDynamicSecret.mutateAsync({ + name: dynamicSecret.name, + path: secretPath, + projectSlug, + environmentSlug: environment, + data: { + maxTTL: maxTTL || undefined, + defaultTTL, + inputs, + newName: newName === dynamicSecret.name ? undefined : newName, + usernameTemplate: !usernameTemplate || isDefaultUsernameTemplate ? null : usernameTemplate + } + }); + onClose(); + createNotification({ + type: "success", + text: "Successfully updated dynamic secret" + }); }; return ( diff --git a/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretCouchbaseForm.tsx b/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretCouchbaseForm.tsx index e69b3460f..de38358f3 100644 --- a/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretCouchbaseForm.tsx +++ b/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretCouchbaseForm.tsx @@ -386,37 +386,30 @@ export const EditDynamicSecretCouchbaseForm = ({ })() : transformedInputs; - try { - await updateDynamicSecret.mutateAsync({ - name: dynamicSecret.name, - path: secretPath, - projectSlug, - environmentSlug: environment, - data: { - defaultTTL, - maxTTL: maxTTL || undefined, - newName: newName === dynamicSecret.name ? undefined : newName, - metadata, - usernameTemplate: - !usernameTemplate || usernameTemplate === "{{randomUsername}}" - ? undefined - : usernameTemplate, - inputs: finalInputs - } - }); + await updateDynamicSecret.mutateAsync({ + name: dynamicSecret.name, + path: secretPath, + projectSlug, + environmentSlug: environment, + data: { + defaultTTL, + maxTTL: maxTTL || undefined, + newName: newName === dynamicSecret.name ? undefined : newName, + metadata, + usernameTemplate: + !usernameTemplate || usernameTemplate === "{{randomUsername}}" + ? undefined + : usernameTemplate, + inputs: finalInputs + } + }); - createNotification({ - type: "success", - text: "Successfully updated dynamic secret" - }); + createNotification({ + type: "success", + text: "Successfully updated dynamic secret" + }); - onClose(); - } catch (err) { - createNotification({ - type: "error", - text: `Failed to update dynamic secret: ${err}` - }); - } + onClose(); }; return ( diff --git a/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretElasticSearchForm.tsx b/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretElasticSearchForm.tsx index 000762bc5..015f394ea 100644 --- a/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretElasticSearchForm.tsx +++ b/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretElasticSearchForm.tsx @@ -123,31 +123,24 @@ export const EditDynamicSecretElasticSearchForm = ({ // wait till previous request is finished if (updateDynamicSecret.isPending) return; const isDefaultUsernameTemplate = usernameTemplate === "{{randomUsername}}"; - try { - await updateDynamicSecret.mutateAsync({ - name: dynamicSecret.name, - path: secretPath, - projectSlug, - environmentSlug: environment, - data: { - maxTTL: maxTTL || undefined, - defaultTTL, - inputs, - newName: newName === dynamicSecret.name ? undefined : newName, - usernameTemplate: !usernameTemplate || isDefaultUsernameTemplate ? null : usernameTemplate - } - }); - onClose(); - createNotification({ - type: "success", - text: "Successfully updated dynamic secret" - }); - } catch { - createNotification({ - type: "error", - text: "Failed to update dynamic secret" - }); - } + await updateDynamicSecret.mutateAsync({ + name: dynamicSecret.name, + path: secretPath, + projectSlug, + environmentSlug: environment, + data: { + maxTTL: maxTTL || undefined, + defaultTTL, + inputs, + newName: newName === dynamicSecret.name ? undefined : newName, + usernameTemplate: !usernameTemplate || isDefaultUsernameTemplate ? null : usernameTemplate + } + }); + onClose(); + createNotification({ + type: "success", + text: "Successfully updated dynamic secret" + }); }; const selectedAuthType = watch("inputs.auth.type"); diff --git a/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretGcpIamForm.tsx b/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretGcpIamForm.tsx index fb313f730..a2755e9c8 100644 --- a/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretGcpIamForm.tsx +++ b/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretGcpIamForm.tsx @@ -77,30 +77,23 @@ export const EditDynamicSecretGcpIamForm = ({ const handleUpdateDynamicSecret = async ({ inputs, maxTTL, defaultTTL, newName }: TForm) => { // wait till previous request is finished if (updateDynamicSecret.isPending) return; - try { - await updateDynamicSecret.mutateAsync({ - name: dynamicSecret.name, - path: secretPath, - projectSlug, - environmentSlug: environment, - data: { - maxTTL: maxTTL || undefined, - defaultTTL, - inputs, - newName: newName === dynamicSecret.name ? undefined : newName - } - }); - onClose(); - createNotification({ - type: "success", - text: "Successfully updated dynamic secret" - }); - } catch { - createNotification({ - type: "error", - text: "Failed to update dynamic secret" - }); - } + await updateDynamicSecret.mutateAsync({ + name: dynamicSecret.name, + path: secretPath, + projectSlug, + environmentSlug: environment, + data: { + maxTTL: maxTTL || undefined, + defaultTTL, + inputs, + newName: newName === dynamicSecret.name ? undefined : newName + } + }); + onClose(); + createNotification({ + type: "success", + text: "Successfully updated dynamic secret" + }); }; return ( diff --git a/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretGithubForm.tsx b/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretGithubForm.tsx index 434bc9465..b5539d85d 100644 --- a/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretGithubForm.tsx +++ b/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretGithubForm.tsx @@ -61,28 +61,21 @@ export const EditDynamicSecretGithubForm = ({ const handleUpdateDynamicSecret = async ({ inputs, newName }: TForm) => { if (updateDynamicSecret.isPending) return; - try { - await updateDynamicSecret.mutateAsync({ - name: dynamicSecret.name, - path: secretPath, - projectSlug, - environmentSlug: environment, - data: { - inputs, - newName: newName === dynamicSecret.name ? undefined : newName - } - }); - onClose(); - createNotification({ - type: "success", - text: "Successfully updated dynamic secret" - }); - } catch { - createNotification({ - type: "error", - text: "Failed to update dynamic secret" - }); - } + await updateDynamicSecret.mutateAsync({ + name: dynamicSecret.name, + path: secretPath, + projectSlug, + environmentSlug: environment, + data: { + inputs, + newName: newName === dynamicSecret.name ? undefined : newName + } + }); + onClose(); + createNotification({ + type: "success", + text: "Successfully updated dynamic secret" + }); }; return ( diff --git a/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretKubernetesForm.tsx b/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretKubernetesForm.tsx index 95f40f9f5..e599c2d6a 100644 --- a/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretKubernetesForm.tsx +++ b/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretKubernetesForm.tsx @@ -189,38 +189,29 @@ export const EditDynamicSecretKubernetesForm = ({ // wait till previous request is finished if (updateDynamicSecret.isPending) return; const isDefaultUsernameTemplate = formData.usernameTemplate === "{{randomUsername}}"; - try { - await updateDynamicSecret.mutateAsync({ - name: dynamicSecret.name, - path: secretPath, - projectSlug, - environmentSlug: environment, - data: { - inputs: { - ...formData.inputs, - url: formData.inputs.url || undefined - }, - newName: formData.newName === dynamicSecret.name ? undefined : formData.newName, - defaultTTL: formData.defaultTTL, - maxTTL: formData.maxTTL, - usernameTemplate: - !formData.usernameTemplate || isDefaultUsernameTemplate - ? null - : formData.usernameTemplate - } - }); + await updateDynamicSecret.mutateAsync({ + name: dynamicSecret.name, + path: secretPath, + projectSlug, + environmentSlug: environment, + data: { + inputs: { + ...formData.inputs, + url: formData.inputs.url || undefined + }, + newName: formData.newName === dynamicSecret.name ? undefined : formData.newName, + defaultTTL: formData.defaultTTL, + maxTTL: formData.maxTTL, + usernameTemplate: + !formData.usernameTemplate || isDefaultUsernameTemplate ? null : formData.usernameTemplate + } + }); - onClose(); - createNotification({ - type: "success", - text: "Successfully updated dynamic secret" - }); - } catch (err) { - createNotification({ - type: "error", - text: err instanceof Error ? err.message : "Failed to update dynamic secret" - }); - } + onClose(); + createNotification({ + type: "success", + text: "Successfully updated dynamic secret" + }); }; return ( diff --git a/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretLdapForm.tsx b/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretLdapForm.tsx index 09d345d3d..e95d89561 100644 --- a/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretLdapForm.tsx +++ b/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretLdapForm.tsx @@ -119,31 +119,24 @@ export const EditDynamicSecretLdapForm = ({ if (updateDynamicSecret.isPending) return; const isDefaultUsernameTemplate = usernameTemplate === "{{randomUsername}}"; - try { - await updateDynamicSecret.mutateAsync({ - name: dynamicSecret.name, - path: secretPath, - projectSlug, - environmentSlug: environment, - data: { - maxTTL: maxTTL || undefined, - defaultTTL, - inputs, - newName: newName === dynamicSecret.name ? undefined : newName, - usernameTemplate: !usernameTemplate || isDefaultUsernameTemplate ? null : usernameTemplate - } - }); - onClose(); - createNotification({ - type: "success", - text: "Successfully updated dynamic secret" - }); - } catch { - createNotification({ - type: "error", - text: "Failed to update dynamic secret" - }); - } + await updateDynamicSecret.mutateAsync({ + name: dynamicSecret.name, + path: secretPath, + projectSlug, + environmentSlug: environment, + data: { + maxTTL: maxTTL || undefined, + defaultTTL, + inputs, + newName: newName === dynamicSecret.name ? undefined : newName, + usernameTemplate: !usernameTemplate || isDefaultUsernameTemplate ? null : usernameTemplate + } + }); + onClose(); + createNotification({ + type: "success", + text: "Successfully updated dynamic secret" + }); }; return ( diff --git a/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretMongoAtlasForm.tsx b/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretMongoAtlasForm.tsx index 5b577192a..905e00660 100644 --- a/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretMongoAtlasForm.tsx +++ b/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretMongoAtlasForm.tsx @@ -142,31 +142,24 @@ export const EditDynamicSecretMongoAtlasForm = ({ if (updateDynamicSecret.isPending) return; const isDefaultUsernameTemplate = usernameTemplate === "{{randomUsername}}"; - try { - await updateDynamicSecret.mutateAsync({ - name: dynamicSecret.name, - path: secretPath, - projectSlug, - environmentSlug: environment, - data: { - maxTTL: maxTTL || undefined, - defaultTTL, - inputs, - newName: newName === dynamicSecret.name ? undefined : newName, - usernameTemplate: !usernameTemplate || isDefaultUsernameTemplate ? null : usernameTemplate - } - }); - onClose(); - createNotification({ - type: "success", - text: "Successfully updated dynamic secret" - }); - } catch { - createNotification({ - type: "error", - text: "Failed to update dynamic secret" - }); - } + await updateDynamicSecret.mutateAsync({ + name: dynamicSecret.name, + path: secretPath, + projectSlug, + environmentSlug: environment, + data: { + maxTTL: maxTTL || undefined, + defaultTTL, + inputs, + newName: newName === dynamicSecret.name ? undefined : newName, + usernameTemplate: !usernameTemplate || isDefaultUsernameTemplate ? null : usernameTemplate + } + }); + onClose(); + createNotification({ + type: "success", + text: "Successfully updated dynamic secret" + }); }; return ( diff --git a/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretMongoDBForm.tsx b/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretMongoDBForm.tsx index 90c31e1f0..d5b63a1cf 100644 --- a/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretMongoDBForm.tsx +++ b/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretMongoDBForm.tsx @@ -108,36 +108,28 @@ export const EditDynamicSecretMongoDBForm = ({ if (updateDynamicSecret.isPending) return; const isDefaultUsernameTemplate = usernameTemplate === "{{randomUsername}}"; - try { - await updateDynamicSecret.mutateAsync({ - name: dynamicSecret.name, - path: secretPath, - projectSlug, - environmentSlug: environment, - data: { - maxTTL: maxTTL || undefined, - defaultTTL, - inputs: { - ...inputs, - port: inputs?.port ? inputs.port : undefined, - roles: inputs?.roles?.map((el) => el.roleName) - }, - usernameTemplate: - !usernameTemplate || isDefaultUsernameTemplate ? null : usernameTemplate, - newName: newName === dynamicSecret.name ? undefined : newName - } - }); - onClose(); - createNotification({ - type: "success", - text: "Successfully updated dynamic secret" - }); - } catch { - createNotification({ - type: "error", - text: "Failed to update dynamic secret" - }); - } + await updateDynamicSecret.mutateAsync({ + name: dynamicSecret.name, + path: secretPath, + projectSlug, + environmentSlug: environment, + data: { + maxTTL: maxTTL || undefined, + defaultTTL, + inputs: { + ...inputs, + port: inputs?.port ? inputs.port : undefined, + roles: inputs?.roles?.map((el) => el.roleName) + }, + usernameTemplate: !usernameTemplate || isDefaultUsernameTemplate ? null : usernameTemplate, + newName: newName === dynamicSecret.name ? undefined : newName + } + }); + onClose(); + createNotification({ + type: "success", + text: "Successfully updated dynamic secret" + }); }; return ( diff --git a/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretRabbitMqForm.tsx b/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretRabbitMqForm.tsx index 984e68831..dbf0d90d0 100644 --- a/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretRabbitMqForm.tsx +++ b/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretRabbitMqForm.tsx @@ -100,31 +100,24 @@ export const EditDynamicSecretRabbitMqForm = ({ if (updateDynamicSecret.isPending) return; const isDefaultUsernameTemplate = usernameTemplate === "{{randomUsername}}"; - try { - await updateDynamicSecret.mutateAsync({ - name: dynamicSecret.name, - path: secretPath, - projectSlug, - environmentSlug: environment, - data: { - maxTTL: maxTTL || undefined, - defaultTTL, - inputs, - newName: newName === dynamicSecret.name ? undefined : newName, - usernameTemplate: !usernameTemplate || isDefaultUsernameTemplate ? null : usernameTemplate - } - }); - onClose(); - createNotification({ - type: "success", - text: "Successfully updated dynamic secret" - }); - } catch { - createNotification({ - type: "error", - text: "Failed to update dynamic secret" - }); - } + await updateDynamicSecret.mutateAsync({ + name: dynamicSecret.name, + path: secretPath, + projectSlug, + environmentSlug: environment, + data: { + maxTTL: maxTTL || undefined, + defaultTTL, + inputs, + newName: newName === dynamicSecret.name ? undefined : newName, + usernameTemplate: !usernameTemplate || isDefaultUsernameTemplate ? null : usernameTemplate + } + }); + onClose(); + createNotification({ + type: "success", + text: "Successfully updated dynamic secret" + }); }; const selectedTags = watch("inputs.tags"); diff --git a/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretRedisProviderForm.tsx b/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretRedisProviderForm.tsx index bc21a17d7..add8d6042 100644 --- a/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretRedisProviderForm.tsx +++ b/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretRedisProviderForm.tsx @@ -102,32 +102,24 @@ export const EditDynamicSecretRedisProviderForm = ({ // wait till previous request is finished if (updateDynamicSecret.isPending) return; const isDefaultUsernameTemplate = usernameTemplate === "{{randomUsername}}"; - try { - await updateDynamicSecret.mutateAsync({ - name: dynamicSecret.name, - path: secretPath, - projectSlug, - environmentSlug: environment, - data: { - usernameTemplate: - !usernameTemplate || isDefaultUsernameTemplate ? null : usernameTemplate, - maxTTL: maxTTL || undefined, - defaultTTL, - inputs, - newName: newName === dynamicSecret.name ? undefined : newName - } - }); - onClose(); - createNotification({ - type: "success", - text: "Successfully updated dynamic secret" - }); - } catch { - createNotification({ - type: "error", - text: "Failed to update dynamic secret" - }); - } + await updateDynamicSecret.mutateAsync({ + name: dynamicSecret.name, + path: secretPath, + projectSlug, + environmentSlug: environment, + data: { + usernameTemplate: !usernameTemplate || isDefaultUsernameTemplate ? null : usernameTemplate, + maxTTL: maxTTL || undefined, + defaultTTL, + inputs, + newName: newName === dynamicSecret.name ? undefined : newName + } + }); + onClose(); + createNotification({ + type: "success", + text: "Successfully updated dynamic secret" + }); }; return ( diff --git a/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretSapAseForm.tsx b/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretSapAseForm.tsx index 37dbae5ee..2f55cca2b 100644 --- a/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretSapAseForm.tsx +++ b/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretSapAseForm.tsx @@ -101,31 +101,24 @@ export const EditDynamicSecretSapAseForm = ({ if (updateDynamicSecret.isPending) return; const isDefaultUsernameTemplate = usernameTemplate === "{{randomUsername}}"; - try { - await updateDynamicSecret.mutateAsync({ - name: dynamicSecret.name, - path: secretPath, - projectSlug, - environmentSlug: environment, - data: { - maxTTL: maxTTL || undefined, - defaultTTL, - inputs, - newName: newName === dynamicSecret.name ? undefined : newName, - usernameTemplate: !usernameTemplate || isDefaultUsernameTemplate ? null : usernameTemplate - } - }); - onClose(); - createNotification({ - type: "success", - text: "Successfully updated dynamic secret" - }); - } catch { - createNotification({ - type: "error", - text: "Failed to update dynamic secret" - }); - } + await updateDynamicSecret.mutateAsync({ + name: dynamicSecret.name, + path: secretPath, + projectSlug, + environmentSlug: environment, + data: { + maxTTL: maxTTL || undefined, + defaultTTL, + inputs, + newName: newName === dynamicSecret.name ? undefined : newName, + usernameTemplate: !usernameTemplate || isDefaultUsernameTemplate ? null : usernameTemplate + } + }); + onClose(); + createNotification({ + type: "success", + text: "Successfully updated dynamic secret" + }); }; return ( diff --git a/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretSapHanaForm.tsx b/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretSapHanaForm.tsx index 430f13e83..d0f6a9d90 100644 --- a/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretSapHanaForm.tsx +++ b/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretSapHanaForm.tsx @@ -101,31 +101,24 @@ export const EditDynamicSecretSapHanaForm = ({ if (updateDynamicSecret.isPending) return; const isDefaultUsernameTemplate = usernameTemplate === "{{randomUsername}}"; - try { - await updateDynamicSecret.mutateAsync({ - name: dynamicSecret.name, - path: secretPath, - projectSlug, - environmentSlug: environment, - data: { - maxTTL: maxTTL || undefined, - defaultTTL, - inputs, - newName: newName === dynamicSecret.name ? undefined : newName, - usernameTemplate: !usernameTemplate || isDefaultUsernameTemplate ? null : usernameTemplate - } - }); - onClose(); - createNotification({ - type: "success", - text: "Successfully updated dynamic secret" - }); - } catch { - createNotification({ - type: "error", - text: "Failed to update dynamic secret" - }); - } + await updateDynamicSecret.mutateAsync({ + name: dynamicSecret.name, + path: secretPath, + projectSlug, + environmentSlug: environment, + data: { + maxTTL: maxTTL || undefined, + defaultTTL, + inputs, + newName: newName === dynamicSecret.name ? undefined : newName, + usernameTemplate: !usernameTemplate || isDefaultUsernameTemplate ? null : usernameTemplate + } + }); + onClose(); + createNotification({ + type: "success", + text: "Successfully updated dynamic secret" + }); }; return ( diff --git a/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretSnowflakeForm.tsx b/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretSnowflakeForm.tsx index 1cbc20cfb..384278494 100644 --- a/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretSnowflakeForm.tsx +++ b/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretSnowflakeForm.tsx @@ -97,32 +97,25 @@ export const EditDynamicSecretSnowflakeForm = ({ }: TForm) => { // wait till previous request is finished if (updateDynamicSecret.isPending) return; - try { - const isDefaultUsernameTemplate = usernameTemplate === "{{randomUsername}}"; - await updateDynamicSecret.mutateAsync({ - name: dynamicSecret.name, - path: secretPath, - projectSlug, - environmentSlug: environment, - data: { - maxTTL: maxTTL || undefined, - defaultTTL, - inputs, - newName: newName === dynamicSecret.name ? undefined : newName, - usernameTemplate: !usernameTemplate || isDefaultUsernameTemplate ? null : usernameTemplate - } - }); - onClose(); - createNotification({ - type: "success", - text: "Successfully updated dynamic secret" - }); - } catch (err) { - createNotification({ - type: "error", - text: err instanceof Error ? err.message : "Failed to update dynamic secret" - }); - } + const isDefaultUsernameTemplate = usernameTemplate === "{{randomUsername}}"; + await updateDynamicSecret.mutateAsync({ + name: dynamicSecret.name, + path: secretPath, + projectSlug, + environmentSlug: environment, + data: { + maxTTL: maxTTL || undefined, + defaultTTL, + inputs, + newName: newName === dynamicSecret.name ? undefined : newName, + usernameTemplate: !usernameTemplate || isDefaultUsernameTemplate ? null : usernameTemplate + } + }); + onClose(); + createNotification({ + type: "success", + text: "Successfully updated dynamic secret" + }); }; return ( diff --git a/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretSqlProviderForm.tsx b/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretSqlProviderForm.tsx index 929a1485d..d6da25f80 100644 --- a/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretSqlProviderForm.tsx +++ b/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretSqlProviderForm.tsx @@ -167,36 +167,29 @@ export const EditDynamicSecretSqlProviderForm = ({ }: TForm) => { // wait till previous request is finished if (updateDynamicSecret.isPending) return; - try { - const isDefaultUsernameTemplate = usernameTemplate === "{{randomUsername}}"; - await updateDynamicSecret.mutateAsync({ - name: dynamicSecret.name, - path: secretPath, - projectSlug, - environmentSlug: environment, - data: { - maxTTL: maxTTL || undefined, - defaultTTL, - inputs: { - ...inputs, - gatewayId: isGatewayInActive ? null : inputs.gatewayId - }, - newName: newName === dynamicSecret.name ? undefined : newName, - metadata, - usernameTemplate: !usernameTemplate || isDefaultUsernameTemplate ? null : usernameTemplate - } - }); - onClose(); - createNotification({ - type: "success", - text: "Successfully updated dynamic secret" - }); - } catch { - createNotification({ - type: "error", - text: "Failed to update dynamic secret" - }); - } + const isDefaultUsernameTemplate = usernameTemplate === "{{randomUsername}}"; + await updateDynamicSecret.mutateAsync({ + name: dynamicSecret.name, + path: secretPath, + projectSlug, + environmentSlug: environment, + data: { + maxTTL: maxTTL || undefined, + defaultTTL, + inputs: { + ...inputs, + gatewayId: isGatewayInActive ? null : inputs.gatewayId + }, + newName: newName === dynamicSecret.name ? undefined : newName, + metadata, + usernameTemplate: !usernameTemplate || isDefaultUsernameTemplate ? null : usernameTemplate + } + }); + onClose(); + createNotification({ + type: "success", + text: "Successfully updated dynamic secret" + }); }; return ( diff --git a/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretTotpForm.tsx b/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretTotpForm.tsx index 7b4a4dac3..15dead8d0 100644 --- a/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretTotpForm.tsx +++ b/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretTotpForm.tsx @@ -87,28 +87,21 @@ export const EditDynamicSecretTotpForm = ({ const handleUpdateDynamicSecret = async ({ inputs, newName }: TForm) => { // wait till previous request is finished if (updateDynamicSecret.isPending) return; - try { - await updateDynamicSecret.mutateAsync({ - name: dynamicSecret.name, - path: secretPath, - projectSlug, - environmentSlug: environment, - data: { - inputs, - newName: newName === dynamicSecret.name ? undefined : newName - } - }); - onClose(); - createNotification({ - type: "success", - text: "Successfully updated dynamic secret" - }); - } catch (err) { - createNotification({ - type: "error", - text: err instanceof Error ? err.message : "Failed to update dynamic secret" - }); - } + await updateDynamicSecret.mutateAsync({ + name: dynamicSecret.name, + path: secretPath, + projectSlug, + environmentSlug: environment, + data: { + inputs, + newName: newName === dynamicSecret.name ? undefined : newName + } + }); + onClose(); + createNotification({ + type: "success", + text: "Successfully updated dynamic secret" + }); }; return ( diff --git a/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretVertica.tsx b/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretVertica.tsx index e4ccda943..0579ba3b9 100644 --- a/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretVertica.tsx +++ b/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/EditDynamicSecretForm/EditDynamicSecretVertica.tsx @@ -146,34 +146,28 @@ export const EditDynamicSecretVerticaForm = ({ if (updateDynamicSecret.isPending) return; const isDefaultUsernameTemplate = usernameTemplate === "{{randomUsername}}"; - try { - await updateDynamicSecret.mutateAsync({ - name: dynamicSecret.name, - path: secretPath, - projectSlug, - environmentSlug: environment, - data: { - maxTTL: maxTTL || undefined, - defaultTTL, - inputs: { - ...inputs, - gatewayId: isGatewayInActive ? null : inputs.gatewayId - }, - newName: newName === dynamicSecret.name ? undefined : newName, - usernameTemplate: !usernameTemplate || isDefaultUsernameTemplate ? null : usernameTemplate - } - }); - onClose(); - createNotification({ - type: "success", - text: "Successfully updated dynamic secret" - }); - } catch { - createNotification({ - type: "error", - text: "Failed to update dynamic secret" - }); - } + + await updateDynamicSecret.mutateAsync({ + name: dynamicSecret.name, + path: secretPath, + projectSlug, + environmentSlug: environment, + data: { + maxTTL: maxTTL || undefined, + defaultTTL, + inputs: { + ...inputs, + gatewayId: isGatewayInActive ? null : inputs.gatewayId + }, + newName: newName === dynamicSecret.name ? undefined : newName, + usernameTemplate: !usernameTemplate || isDefaultUsernameTemplate ? null : usernameTemplate + } + }); + onClose(); + createNotification({ + type: "success", + text: "Successfully updated dynamic secret" + }); }; return ( diff --git a/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/RenewDynamicSecretLease.tsx b/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/RenewDynamicSecretLease.tsx index 85528a5bc..bdb5f9add 100644 --- a/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/RenewDynamicSecretLease.tsx +++ b/frontend/src/pages/secret-manager/SecretDashboardPage/components/DynamicSecretListView/RenewDynamicSecretLease.tsx @@ -64,27 +64,19 @@ export const RenewDynamicSecretLease = ({ const handleDynamicSecretLeaseCreate = async ({ ttl }: TForm) => { if (renewDynamicSecretLease.isPending) return; - try { - await renewDynamicSecretLease.mutateAsync({ - environmentSlug: environment, - projectSlug, - path: secretPath, - ttl, - dynamicSecretName, - leaseId - }); - onClose(); - createNotification({ - type: "success", - text: "Successfully renewed lease" - }); - } catch (error) { - console.log(error); - createNotification({ - type: "error", - text: "Failed to renew lease" - }); - } + await renewDynamicSecretLease.mutateAsync({ + environmentSlug: environment, + projectSlug, + path: secretPath, + ttl, + dynamicSecretName, + leaseId + }); + onClose(); + createNotification({ + type: "success", + text: "Successfully renewed lease" + }); }; return ( diff --git a/frontend/src/pages/secret-manager/SecretDashboardPage/components/FolderListView/FolderListView.tsx b/frontend/src/pages/secret-manager/SecretDashboardPage/components/FolderListView/FolderListView.tsx index bd812b837..6e39b8ffc 100644 --- a/frontend/src/pages/secret-manager/SecretDashboardPage/components/FolderListView/FolderListView.tsx +++ b/frontend/src/pages/secret-manager/SecretDashboardPage/components/FolderListView/FolderListView.tsx @@ -69,73 +69,65 @@ export const FolderListView = ({ oldFolderName?: string, oldFolderDescription?: string ) => { - try { - const updateFolderData = popUp.updateFolder.data; - if (!updateFolderData) throw new Error("Update folder data is required"); - const { id: folderId, pendingAction, isPending } = updateFolderData as TSecretFolder; + const updateFolderData = popUp.updateFolder.data; + if (!updateFolderData) throw new Error("Update folder data is required"); + const { id: folderId, pendingAction, isPending } = updateFolderData as TSecretFolder; - if (isBatchMode) { - const isEditingPendingCreation = isPending && pendingAction === PendingAction.Create; + if (isBatchMode) { + const isEditingPendingCreation = isPending && pendingAction === PendingAction.Create; - if (isEditingPendingCreation) { - const updatedCreate: PendingFolderCreate = { - id: folderId, - type: PendingAction.Create, - folderName: newFolderName, - description: newFolderDescription || undefined, - parentPath: secretPath, - timestamp: Date.now(), - resourceType: "folder" - }; + if (isEditingPendingCreation) { + const updatedCreate: PendingFolderCreate = { + id: folderId, + type: PendingAction.Create, + folderName: newFolderName, + description: newFolderDescription || undefined, + parentPath: secretPath, + timestamp: Date.now(), + resourceType: "folder" + }; - addPendingChange(updatedCreate, { - projectId, - environment, - secretPath - }); - } else { - const updateChange: PendingFolderUpdate = { - id: folderId, - type: PendingAction.Update, - originalFolderName: oldFolderName || "", - folderName: newFolderName, - originalDescription: oldFolderDescription, - description: newFolderDescription || undefined, - timestamp: Date.now(), - resourceType: "folder" - }; + addPendingChange(updatedCreate, { + projectId, + environment, + secretPath + }); + } else { + const updateChange: PendingFolderUpdate = { + id: folderId, + type: PendingAction.Update, + originalFolderName: oldFolderName || "", + folderName: newFolderName, + originalDescription: oldFolderDescription, + description: newFolderDescription || undefined, + timestamp: Date.now(), + resourceType: "folder" + }; - addPendingChange(updateChange, { - projectId, - environment, - secretPath - }); - } - - handlePopUpClose("updateFolder"); - return; + addPendingChange(updateChange, { + projectId, + environment, + secretPath + }); } - await updateFolder({ - folderId, - name: newFolderName, - path: secretPath, - environment, - projectId, - description: newFolderDescription - }); handlePopUpClose("updateFolder"); - createNotification({ - type: "success", - text: "Successfully saved folder" - }); - } catch (error) { - console.log(error); - createNotification({ - type: "error", - text: "Failed to save folder" - }); + return; } + + await updateFolder({ + folderId, + name: newFolderName, + path: secretPath, + environment, + projectId, + description: newFolderDescription + }); + handlePopUpClose("updateFolder"); + createNotification({ + type: "success", + text: "Successfully saved folder" + }); }; const handleDeletePending = (id: string) => { @@ -147,48 +139,40 @@ export const FolderListView = ({ }; const handleFolderDelete = async () => { - try { - const folderData = popUp.deleteFolder?.data as TSecretFolder; + const folderData = popUp.deleteFolder?.data as TSecretFolder; - if (isBatchMode) { - const pendingFolderDelete: PendingFolderDelete = { - id: folderData.id, - folderName: folderData.name, - folderPath: secretPath, - resourceType: "folder", - type: PendingAction.Delete, - timestamp: Date.now() - }; + if (isBatchMode) { + const pendingFolderDelete: PendingFolderDelete = { + id: folderData.id, + folderName: folderData.name, + folderPath: secretPath, + resourceType: "folder", + type: PendingAction.Delete, + timestamp: Date.now() + }; - addPendingChange(pendingFolderDelete, { - projectId, - environment, - secretPath - }); - - handlePopUpClose("deleteFolder"); - return; - } - - await deleteFolder({ - folderId: folderData.id, - path: secretPath, + addPendingChange(pendingFolderDelete, { + projectId, environment, - projectId + secretPath }); handlePopUpClose("deleteFolder"); - createNotification({ - type: "success", - text: "Successfully deleted folder" - }); - } catch (error) { - console.log(error); - createNotification({ - type: "error", - text: "Failed to delete folder" - }); + return; } + + await deleteFolder({ + folderId: folderData.id, + path: secretPath, + environment, + projectId + }); + + handlePopUpClose("deleteFolder"); + createNotification({ + type: "success", + text: "Successfully deleted folder" + }); }; const handleFolderClick = (name: string, isPending?: boolean) => { diff --git a/frontend/src/pages/secret-manager/SecretDashboardPage/components/SecretImportListView/SecretImportItem.tsx b/frontend/src/pages/secret-manager/SecretDashboardPage/components/SecretImportListView/SecretImportItem.tsx index d4e7d42d5..6a127d6b5 100644 --- a/frontend/src/pages/secret-manager/SecretDashboardPage/components/SecretImportListView/SecretImportItem.tsx +++ b/frontend/src/pages/secret-manager/SecretDashboardPage/components/SecretImportListView/SecretImportItem.tsx @@ -118,24 +118,16 @@ export const SecretImportItem = ({ const handleResyncSecretReplication = async () => { if (resyncSecretReplication.isPending) return; - try { - await resyncSecretReplication.mutateAsync({ - id, - environment, - path: secretPath, - projectId: currentProject?.id || "" - }); - createNotification({ - text: "Please refresh the dashboard to view changes", - type: "success" - }); - } catch (error) { - console.error(error); - createNotification({ - text: "Failed to resync replication", - type: "error" - }); - } + await resyncSecretReplication.mutateAsync({ + id, + environment, + path: secretPath, + projectId: currentProject?.id || "" + }); + createNotification({ + text: "Please refresh the dashboard to view changes", + type: "success" + }); }; const handleRowClick = () => { diff --git a/frontend/src/pages/secret-manager/SecretDashboardPage/components/SecretImportListView/SecretImportListView.tsx b/frontend/src/pages/secret-manager/SecretDashboardPage/components/SecretImportListView/SecretImportListView.tsx index 763872e9e..794fce88f 100644 --- a/frontend/src/pages/secret-manager/SecretDashboardPage/components/SecretImportListView/SecretImportListView.tsx +++ b/frontend/src/pages/secret-manager/SecretDashboardPage/components/SecretImportListView/SecretImportListView.tsx @@ -147,25 +147,17 @@ export const SecretImportListView = ({ const handleSecretImportDelete = async () => { const { id: secretImportId } = popUp.deleteSecretImport?.data as { id: string }; - try { - await deleteSecretImport({ - projectId, - environment, - path: secretPath, - id: secretImportId - }); - handlePopUpClose("deleteSecretImport"); - createNotification({ - type: "success", - text: "Successfully removed secret link" - }); - } catch (err) { - console.error(err); - createNotification({ - text: "Failed to remove secret link", - type: "error" - }); - } + await deleteSecretImport({ + projectId, + environment, + path: secretPath, + id: secretImportId + }); + handlePopUpClose("deleteSecretImport"); + createNotification({ + type: "success", + text: "Successfully removed secret link" + }); }; const handleSecretImportReorder = ({ over, active }: DragEndEvent) => { diff --git a/frontend/src/pages/secret-manager/SecretDashboardPage/components/SecretListView/CreateReminderForm.tsx b/frontend/src/pages/secret-manager/SecretDashboardPage/components/SecretListView/CreateReminderForm.tsx index 3f7727290..531401998 100644 --- a/frontend/src/pages/secret-manager/SecretDashboardPage/components/SecretListView/CreateReminderForm.tsx +++ b/frontend/src/pages/secret-manager/SecretDashboardPage/components/SecretListView/CreateReminderForm.tsx @@ -199,53 +199,37 @@ export const CreateReminderForm = ({ // Form submission handler const handleFormSubmit = async (data: TReminderFormSchema) => { - try { - await createReminder({ - repeatDays: data.repeatDays, - message: data.message, - recipients: data.recipients?.map((r) => r.value) || [], - secretId, - nextReminderDate: data.nextReminderDate, - fromDate: data.fromDate - }); + await createReminder({ + repeatDays: data.repeatDays, + message: data.message, + recipients: data.recipients?.map((r) => r.value) || [], + secretId, + nextReminderDate: data.nextReminderDate, + fromDate: data.fromDate + }); - invalidateQueries(); + invalidateQueries(); - createNotification({ - type: "success", - text: `Successfully ${isEditMode ? "updated" : "created"} secret reminder` - }); + createNotification({ + type: "success", + text: `Successfully ${isEditMode ? "updated" : "created"} secret reminder` + }); - reset(); - onOpenChange(); - } catch (error) { - console.error("Failed to save reminder:", error); - createNotification({ - type: "error", - text: "Failed to save reminder. Please try again." - }); - } + reset(); + onOpenChange(); }; // Delete reminder handler const handleDeleteReminder = async () => { - try { - await deleteReminder({ reminderId: reminder?.id || "", secretId }); - invalidateQueries(); - reset(); - onOpenChange(); + await deleteReminder({ reminderId: reminder?.id || "", secretId }); + invalidateQueries(); + reset(); + onOpenChange(); - createNotification({ - type: "success", - text: "Successfully deleted reminder" - }); - } catch (error) { - console.error("Failed to delete reminder:", error); - createNotification({ - type: "error", - text: "Failed to delete reminder. Please try again." - }); - } + createNotification({ + type: "success", + text: "Successfully deleted reminder" + }); }; // Handle reminder type change diff --git a/frontend/src/pages/secret-manager/SecretDashboardPage/components/SecretListView/SecretListView.tsx b/frontend/src/pages/secret-manager/SecretDashboardPage/components/SecretListView/SecretListView.tsx index bd43e1271..be5dfaaed 100644 --- a/frontend/src/pages/secret-manager/SecretDashboardPage/components/SecretListView/SecretListView.tsx +++ b/frontend/src/pages/secret-manager/SecretDashboardPage/components/SecretListView/SecretListView.tsx @@ -293,174 +293,166 @@ export const SecretListView = ({ isSameTags && isSameRecipients; - try { - // personal secret change - let personalAction = false; - if (overrideAction === "deleted") { - await handleSecretOperation("delete", SecretType.Personal, oldKey, { - secretId: orgSecret.idOverride - }); - personalAction = true; - } else if (overrideAction && idOverride) { - await handleSecretOperation("update", SecretType.Personal, oldKey, { - value: valueOverride, - newKey: hasKeyChanged ? key : undefined, - secretId: orgSecret.idOverride, - skipMultilineEncoding: modSecret.skipMultilineEncoding - }); - personalAction = true; - } else if (overrideAction) { - await handleSecretOperation("create", SecretType.Personal, oldKey, { - value: valueOverride - }); - personalAction = true; - } + // personal secret change + let personalAction = false; + if (overrideAction === "deleted") { + await handleSecretOperation("delete", SecretType.Personal, oldKey, { + secretId: orgSecret.idOverride + }); + personalAction = true; + } else if (overrideAction && idOverride) { + await handleSecretOperation("update", SecretType.Personal, oldKey, { + value: valueOverride, + newKey: hasKeyChanged ? key : undefined, + secretId: orgSecret.idOverride, + skipMultilineEncoding: modSecret.skipMultilineEncoding + }); + personalAction = true; + } else if (overrideAction) { + await handleSecretOperation("create", SecretType.Personal, oldKey, { + value: valueOverride + }); + personalAction = true; + } - // shared secret change - if (!isSharedSecUnchanged && !personalAction) { - if (isBatchMode) { - const isEditingPendingCreation = isPending && pendingAction === PendingAction.Create; + // shared secret change + if (!isSharedSecUnchanged && !personalAction) { + if (isBatchMode) { + const isEditingPendingCreation = isPending && pendingAction === PendingAction.Create; - if (isEditingPendingCreation) { - const updatedCreate: PendingSecretCreate = { - id: orgSecret.id, - type: PendingAction.Create, - secretKey: key, - secretValue: value || "", - secretComment: comment || "", - skipMultilineEncoding: modSecret.skipMultilineEncoding || false, - tags: tags?.map((tag) => ({ id: tag.id, slug: tag.name || tag.slug || "" })) || [], - secretMetadata: secretMetadata || [], - timestamp: Date.now(), - resourceType: "secret", - originalKey: oldKey - }; + if (isEditingPendingCreation) { + const updatedCreate: PendingSecretCreate = { + id: orgSecret.id, + type: PendingAction.Create, + secretKey: key, + secretValue: value || "", + secretComment: comment || "", + skipMultilineEncoding: modSecret.skipMultilineEncoding || false, + tags: tags?.map((tag) => ({ id: tag.id, slug: tag.name || tag.slug || "" })) || [], + secretMetadata: secretMetadata || [], + timestamp: Date.now(), + resourceType: "secret", + originalKey: oldKey + }; - addPendingChange(updatedCreate, { - projectId, - environment, - secretPath - }); - } else { - const trueOriginalSecret = getTrueOriginalSecret( - orgSecret, - pendingChangesRef.current.secrets - ); + addPendingChange(updatedCreate, { + projectId, + environment, + secretPath + }); + } else { + const trueOriginalSecret = getTrueOriginalSecret( + orgSecret, + pendingChangesRef.current.secrets + ); - const updateChange: PendingSecretUpdate = { - id: orgSecret.id, - type: PendingAction.Update, - secretKey: trueOriginalSecret.key, - newSecretName: key, - originalValue: trueOriginalSecret.value, - secretValue: value, - originalComment: trueOriginalSecret.comment, - secretComment: comment, - originalSkipMultilineEncoding: trueOriginalSecret.skipMultilineEncoding, - skipMultilineEncoding: modSecret.skipMultilineEncoding, - originalTags: - trueOriginalSecret.tags?.map((tag) => ({ id: tag.id, slug: tag.slug })) || [], - tags: tags?.map((tag) => ({ id: tag.id, slug: tag.name || tag.slug || "" })) || [], - originalSecretMetadata: trueOriginalSecret.secretMetadata || [], - secretMetadata: secretMetadata || [], - timestamp: Date.now(), - resourceType: "secret", - existingSecret: orgSecret - }; + const updateChange: PendingSecretUpdate = { + id: orgSecret.id, + type: PendingAction.Update, + secretKey: trueOriginalSecret.key, + newSecretName: key, + originalValue: trueOriginalSecret.value, + secretValue: value, + originalComment: trueOriginalSecret.comment, + secretComment: comment, + originalSkipMultilineEncoding: trueOriginalSecret.skipMultilineEncoding, + skipMultilineEncoding: modSecret.skipMultilineEncoding, + originalTags: + trueOriginalSecret.tags?.map((tag) => ({ id: tag.id, slug: tag.slug })) || [], + tags: tags?.map((tag) => ({ id: tag.id, slug: tag.name || tag.slug || "" })) || [], + originalSecretMetadata: trueOriginalSecret.secretMetadata || [], + secretMetadata: secretMetadata || [], + timestamp: Date.now(), + resourceType: "secret", + existingSecret: orgSecret + }; - addPendingChange(updateChange, { - projectId, - environment, - secretPath - }); - } - - if (!isReminderEvent) { - handlePopUpClose("secretDetail"); - } - if (cb) cb(); - return; + addPendingChange(updateChange, { + projectId, + environment, + secretPath + }); } - await handleSecretOperation("update", SecretType.Shared, oldKey, { - value, - tags: tagIds, - comment, - reminderRepeatDays, - reminderNote, - reminderRecipients, - secretId: orgSecret.id, - newKey: hasKeyChanged ? key : undefined, - skipMultilineEncoding: modSecret.skipMultilineEncoding, - secretMetadata, - isRotatedSecret: orgSecret.isRotatedSecret, - secretValueHidden - }); + if (!isReminderEvent) { + handlePopUpClose("secretDetail"); + } if (cb) cb(); - } - queryClient.invalidateQueries({ - queryKey: dashboardKeys.getDashboardSecrets({ - projectId, - secretPath - }) - }); - queryClient.invalidateQueries({ - queryKey: secretKeys.getProjectSecret({ projectId, environment, secretPath }) - }); - queryClient.invalidateQueries({ - queryKey: secretSnapshotKeys.list({ - projectId, - environment, - directory: secretPath - }) - }); - queryClient.invalidateQueries({ - queryKey: secretSnapshotKeys.count({ - projectId, - environment, - directory: secretPath - }) - }); - queryClient.invalidateQueries({ - queryKey: commitKeys.count({ projectId, environment, directory: secretPath }) - }); - queryClient.invalidateQueries({ - queryKey: commitKeys.history({ - projectId, - environment, - directory: secretPath - }) - }); - queryClient.invalidateQueries({ - queryKey: secretApprovalRequestKeys.count({ projectId }) - }); - if (!isReminderEvent) { - handlePopUpClose("secretDetail"); + return; } - let successMessage; - if (isReminderEvent) { - successMessage = reminderRepeatDays - ? "Successfully saved secret reminder" - : "Successfully deleted secret reminder"; - } else { - successMessage = "Successfully saved secrets"; - } - - createNotification({ - type: isProtectedBranch && !personalAction ? "info" : "success", - text: - isProtectedBranch && !personalAction - ? "Requested changes have been sent for review" - : successMessage - }); - } catch (error) { - console.log(error); - createNotification({ - type: "error", - text: "Failed to save secret" + await handleSecretOperation("update", SecretType.Shared, oldKey, { + value, + tags: tagIds, + comment, + reminderRepeatDays, + reminderNote, + reminderRecipients, + secretId: orgSecret.id, + newKey: hasKeyChanged ? key : undefined, + skipMultilineEncoding: modSecret.skipMultilineEncoding, + secretMetadata, + isRotatedSecret: orgSecret.isRotatedSecret, + secretValueHidden }); + if (cb) cb(); } + queryClient.invalidateQueries({ + queryKey: dashboardKeys.getDashboardSecrets({ + projectId, + secretPath + }) + }); + queryClient.invalidateQueries({ + queryKey: secretKeys.getProjectSecret({ projectId, environment, secretPath }) + }); + queryClient.invalidateQueries({ + queryKey: secretSnapshotKeys.list({ + projectId, + environment, + directory: secretPath + }) + }); + queryClient.invalidateQueries({ + queryKey: secretSnapshotKeys.count({ + projectId, + environment, + directory: secretPath + }) + }); + queryClient.invalidateQueries({ + queryKey: commitKeys.count({ projectId, environment, directory: secretPath }) + }); + queryClient.invalidateQueries({ + queryKey: commitKeys.history({ + projectId, + environment, + directory: secretPath + }) + }); + queryClient.invalidateQueries({ + queryKey: secretApprovalRequestKeys.count({ projectId }) + }); + if (!isReminderEvent) { + handlePopUpClose("secretDetail"); + } + + let successMessage; + if (isReminderEvent) { + successMessage = reminderRepeatDays + ? "Successfully saved secret reminder" + : "Successfully deleted secret reminder"; + } else { + successMessage = "Successfully saved secrets"; + } + + createNotification({ + type: isProtectedBranch && !personalAction ? "info" : "success", + text: + isProtectedBranch && !personalAction + ? "Requested changes have been sent for review" + : successMessage + }); }, [environment, secretPath, isProtectedBranch, isBatchMode, projectId, addPendingChange] ); @@ -488,75 +480,67 @@ export const SecretListView = ({ value, secretValueHidden } = popUp.deleteSecret?.data as SecretV3RawSanitized; - try { - if (isBatchMode) { - const deleteChange: PendingSecretDelete = { - id: `${secretId}`, - type: PendingAction.Delete, - secretKey: key, - secretValue: value || "", - timestamp: Date.now(), - resourceType: "secret", - secretValueHidden - }; + if (isBatchMode) { + const deleteChange: PendingSecretDelete = { + id: `${secretId}`, + type: PendingAction.Delete, + secretKey: key, + secretValue: value || "", + timestamp: Date.now(), + resourceType: "secret", + secretValueHidden + }; - addPendingChange(deleteChange, { - projectId, - environment, - secretPath - }); + addPendingChange(deleteChange, { + projectId, + environment, + secretPath + }); - handlePopUpClose("deleteSecret"); - handlePopUpClose("secretDetail"); - return; - } - - await handleSecretOperation("delete", SecretType.Shared, key, { secretId }); - // wrap this in another function and then reuse - queryClient.invalidateQueries({ - queryKey: dashboardKeys.getDashboardSecrets({ projectId, secretPath }) - }); - queryClient.invalidateQueries({ - queryKey: secretKeys.getProjectSecret({ projectId, environment, secretPath }) - }); - queryClient.invalidateQueries({ - queryKey: secretSnapshotKeys.list({ - projectId, - environment, - directory: secretPath - }) - }); - queryClient.invalidateQueries({ - queryKey: secretSnapshotKeys.count({ - projectId, - environment, - directory: secretPath - }) - }); - queryClient.invalidateQueries({ - queryKey: commitKeys.count({ projectId, environment, directory: secretPath }) - }); - queryClient.invalidateQueries({ - queryKey: commitKeys.history({ projectId, environment, directory: secretPath }) - }); - queryClient.invalidateQueries({ - queryKey: secretApprovalRequestKeys.count({ projectId }) - }); handlePopUpClose("deleteSecret"); handlePopUpClose("secretDetail"); - createNotification({ - type: isProtectedBranch ? "info" : "success", - text: isProtectedBranch - ? "Requested changes have been sent for review" - : "Successfully deleted secret" - }); - } catch (error) { - console.log(error); - createNotification({ - type: "error", - text: "Failed to delete secret" - }); + return; } + + await handleSecretOperation("delete", SecretType.Shared, key, { secretId }); + // wrap this in another function and then reuse + queryClient.invalidateQueries({ + queryKey: dashboardKeys.getDashboardSecrets({ projectId, secretPath }) + }); + queryClient.invalidateQueries({ + queryKey: secretKeys.getProjectSecret({ projectId, environment, secretPath }) + }); + queryClient.invalidateQueries({ + queryKey: secretSnapshotKeys.list({ + projectId, + environment, + directory: secretPath + }) + }); + queryClient.invalidateQueries({ + queryKey: secretSnapshotKeys.count({ + projectId, + environment, + directory: secretPath + }) + }); + queryClient.invalidateQueries({ + queryKey: commitKeys.count({ projectId, environment, directory: secretPath }) + }); + queryClient.invalidateQueries({ + queryKey: commitKeys.history({ projectId, environment, directory: secretPath }) + }); + queryClient.invalidateQueries({ + queryKey: secretApprovalRequestKeys.count({ projectId }) + }); + handlePopUpClose("deleteSecret"); + handlePopUpClose("secretDetail"); + createNotification({ + type: isProtectedBranch ? "info" : "success", + text: isProtectedBranch + ? "Requested changes have been sent for review" + : "Successfully deleted secret" + }); }, [ (popUp.deleteSecret?.data as SecretV3RawSanitized)?.key, environment, diff --git a/frontend/src/pages/secret-manager/SecretDashboardPage/components/SecretListView/SecretVersionItem.tsx b/frontend/src/pages/secret-manager/SecretDashboardPage/components/SecretListView/SecretVersionItem.tsx index a2c25b13a..525b54444 100644 --- a/frontend/src/pages/secret-manager/SecretDashboardPage/components/SecretListView/SecretVersionItem.tsx +++ b/frontend/src/pages/secret-manager/SecretDashboardPage/components/SecretListView/SecretVersionItem.tsx @@ -2,6 +2,7 @@ import { useState } from "react"; import { faEye } from "@fortawesome/free-regular-svg-icons"; import { faArrowRotateRight, + faBan, faDesktop, faEyeSlash, faServer, @@ -68,10 +69,14 @@ export const SecretVersionItem = ({ const getLinkToModifyHistoryEntity = ( actorId: string, actorType: string, - membershipId: string | null = "" + membershipId: string | null = "", + groupId: string | null = "", + actorName: string | null = "" ) => { switch (actorType) { case ActorType.USER: + if (groupId) + return `/projects/secret-management/${currentProject.id}/groups/${groupId}?username=${actorName}`; return `/projects/secret-management/${currentProject.id}/members/${membershipId}`; case ActorType.IDENTITY: return `/projects/secret-management/${currentProject.id}/identities/${actorId}`; @@ -83,10 +88,26 @@ export const SecretVersionItem = ({ const onModifyHistoryClick = ( actorId: string | undefined | null, actorType: string | undefined | null, - membershipId: string | undefined | null + membershipId: string | undefined | null, + groupId: string | undefined | null, + actorName: string | undefined | null ) => { + if (!membershipId) { + createNotification({ + type: "info", + text: `This ${actorType === ActorType.USER ? "user" : "identity"} is no longer a member of this project.` + }); + return; + } + if (actorType && actorId && actorType !== ActorType.PLATFORM) { - const redirectLink = getLinkToModifyHistoryEntity(actorId, actorType, membershipId); + const redirectLink = getLinkToModifyHistoryEntity( + actorId, + actorType, + membershipId, + groupId, + actorName + ); if (redirectLink) { navigate({ to: redirectLink }); } @@ -157,15 +178,35 @@ export const SecretVersionItem = ({
Modified by: - + {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */}
- onModifyHistoryClick(actor.actorId, actor.actorType, actor.membershipId) + onClick={ + actor.membershipId + ? () => + onModifyHistoryClick( + actor.actorId, + actor.actorType, + actor.membershipId, + actor.groupId, + actor.name + ) + : undefined } - className="cursor-pointer" + className={actor.membershipId ? "cursor-pointer" : undefined} > + {!actor.membershipId && + actor.actorType && + [ActorType.USER, ActorType.IDENTITY].includes( + actor.actorType as ActorType + ) && }
diff --git a/frontend/src/pages/secret-manager/SecretDashboardPage/components/SnapshotView/SnapshotView.tsx b/frontend/src/pages/secret-manager/SecretDashboardPage/components/SnapshotView/SnapshotView.tsx index eed335fa8..ca12e76a4 100644 --- a/frontend/src/pages/secret-manager/SecretDashboardPage/components/SnapshotView/SnapshotView.tsx +++ b/frontend/src/pages/secret-manager/SecretDashboardPage/components/SnapshotView/SnapshotView.tsx @@ -128,25 +128,17 @@ export const SnapshotView = ({ }); return; } - try { - await performRollback({ - projectId, - snapshotId: snapshotData.id, - environment, - directory: secretPath - }); - createNotification({ - text: "Successfully rollback secrets", - type: "success" - }); - onGoBack(); - } catch (error) { - console.log(error); - createNotification({ - text: "Failed to rollback secrets", - type: "error" - }); - } + await performRollback({ + projectId, + snapshotId: snapshotData.id, + environment, + directory: secretPath + }); + createNotification({ + text: "Successfully rollback secrets", + type: "success" + }); + onGoBack(); }; if (isSnapshotLoading) { diff --git a/frontend/src/pages/secret-manager/SecretRotationPage/SecretRotationPage.tsx b/frontend/src/pages/secret-manager/SecretRotationPage/SecretRotationPage.tsx index 5ccdd437d..12c264004 100644 --- a/frontend/src/pages/secret-manager/SecretRotationPage/SecretRotationPage.tsx +++ b/frontend/src/pages/secret-manager/SecretRotationPage/SecretRotationPage.tsx @@ -95,42 +95,26 @@ const Page = () => { const handleDeleteRotation = async () => { const { id } = popUp.deleteRotation.data as { id: string }; - try { - await deleteSecretRotation({ - id, - workspaceId - }); - handlePopUpClose("deleteRotation"); - createNotification({ - type: "success", - text: "Successfully removed rotation" - }); - } catch (error) { - console.log(error); - createNotification({ - type: "error", - text: "Failed to remove rotation" - }); - } + await deleteSecretRotation({ + id, + workspaceId + }); + handlePopUpClose("deleteRotation"); + createNotification({ + type: "success", + text: "Successfully removed rotation" + }); }; const handleRestartRotation = async (id: string) => { - try { - await restartSecretRotation({ - id, - workspaceId - }); - createNotification({ - type: "success", - text: "Secret rotation initiated" - }); - } catch (error) { - console.log(error); - createNotification({ - type: "error", - text: "Failed to restart rotation" - }); - } + await restartSecretRotation({ + id, + workspaceId + }); + createNotification({ + type: "success", + text: "Secret rotation initiated" + }); }; const handleCreateRotation = (provider: TSecretRotationProviderTemplate) => { diff --git a/frontend/src/pages/secret-manager/SecretRotationPage/components/CreateRotationForm/CreateRotationForm.tsx b/frontend/src/pages/secret-manager/SecretRotationPage/components/CreateRotationForm/CreateRotationForm.tsx index 952c869db..cfc34df2c 100644 --- a/frontend/src/pages/secret-manager/SecretRotationPage/components/CreateRotationForm/CreateRotationForm.tsx +++ b/frontend/src/pages/secret-manager/SecretRotationPage/components/CreateRotationForm/CreateRotationForm.tsx @@ -1,7 +1,6 @@ import { useRef, useState } from "react"; import { AnimatePresence, motion } from "framer-motion"; -import { createNotification } from "@app/components/notifications"; import { Modal, ModalContent, Step, Stepper } from "@app/components/v2"; import { useCreateSecretRotation } from "@app/hooks/api"; import { TSecretRotationProviderTemplate } from "@app/hooks/api/types"; @@ -54,27 +53,19 @@ export const CreateRotationForm = ({ const handleFormSubmit = async () => { if (!wizardData.current.input || !wizardData.current.output) return; - try { - await createSecretRotation({ - workspaceId, - provider: provider.name, - customProvider, - secretPath: wizardData.current.output.secretPath, - environment: wizardData.current.output.environment, - interval: wizardData.current.output.interval, - inputs: wizardData.current.input, - outputs: wizardData.current.output.secrets - }); - setWizardStep(0); - onToggle(false); - wizardData.current = {}; - } catch (error) { - console.log(error); - createNotification({ - type: "error", - text: "Failed to create secret rotation" - }); - } + await createSecretRotation({ + workspaceId, + provider: provider.name, + customProvider, + secretPath: wizardData.current.output.secretPath, + environment: wizardData.current.output.environment, + interval: wizardData.current.output.interval, + inputs: wizardData.current.input, + outputs: wizardData.current.output.secrets + }); + setWizardStep(0); + onToggle(false); + wizardData.current = {}; }; return ( diff --git a/frontend/src/pages/secret-manager/SecretSyncDetailsByIDPage/components/SecretSyncActionTriggers.tsx b/frontend/src/pages/secret-manager/SecretSyncDetailsByIDPage/components/SecretSyncActionTriggers.tsx index 78cdf899e..ad82460eb 100644 --- a/frontend/src/pages/secret-manager/SecretSyncDetailsByIDPage/components/SecretSyncActionTriggers.tsx +++ b/frontend/src/pages/secret-manager/SecretSyncDetailsByIDPage/components/SecretSyncActionTriggers.tsx @@ -89,44 +89,30 @@ export const SecretSyncActionTriggers = ({ secretSync }: Props) => { const handleToggleEnableSync = async () => { const isAutoSyncEnabled = !secretSync.isAutoSyncEnabled; - try { - await updateSync.mutateAsync({ - syncId: secretSync.id, - destination: secretSync.destination, - isAutoSyncEnabled, - projectId: secretSync.projectId - }); + await updateSync.mutateAsync({ + syncId: secretSync.id, + destination: secretSync.destination, + isAutoSyncEnabled, + projectId: secretSync.projectId + }); - createNotification({ - text: `Successfully ${isAutoSyncEnabled ? "enabled" : "disabled"} auto-sync for ${destinationName} Sync`, - type: "success" - }); - } catch { - createNotification({ - text: `Failed to ${isAutoSyncEnabled ? "enable" : "disable"} auto-sync for ${destinationName} Sync`, - type: "error" - }); - } + createNotification({ + text: `Successfully ${isAutoSyncEnabled ? "enabled" : "disabled"} auto-sync for ${destinationName} Sync`, + type: "success" + }); }; const handleTriggerSync = async () => { - try { - await triggerSyncSecrets.mutateAsync({ - syncId: secretSync.id, - destination: secretSync.destination, - projectId: secretSync.projectId - }); + await triggerSyncSecrets.mutateAsync({ + syncId: secretSync.id, + destination: secretSync.destination, + projectId: secretSync.projectId + }); - createNotification({ - text: `Successfully triggered ${destinationName} Sync`, - type: "success" - }); - } catch { - createNotification({ - text: `Failed to trigger ${destinationName} Sync`, - type: "error" - }); - } + createNotification({ + text: `Successfully triggered ${destinationName} Sync`, + type: "success" + }); }; const permissionSubject = diff --git a/frontend/src/pages/secret-manager/SettingsPage/components/AutoCapitalizationSection/AutoCapitalizationSection.tsx b/frontend/src/pages/secret-manager/SettingsPage/components/AutoCapitalizationSection/AutoCapitalizationSection.tsx index 73bec81b9..7c9d03904 100644 --- a/frontend/src/pages/secret-manager/SettingsPage/components/AutoCapitalizationSection/AutoCapitalizationSection.tsx +++ b/frontend/src/pages/secret-manager/SettingsPage/components/AutoCapitalizationSection/AutoCapitalizationSection.tsx @@ -13,26 +13,18 @@ export const AutoCapitalizationSection = () => { const { mutateAsync } = useUpdateProject(); const handleToggleCapitalizationToggle = async (state: boolean) => { - try { - if (!currentProject?.id) return; + if (!currentProject?.id) return; - await mutateAsync({ - projectId: currentProject.id, - autoCapitalization: state - }); + await mutateAsync({ + projectId: currentProject.id, + autoCapitalization: state + }); - const text = `Successfully ${state ? "enabled" : "disabled"} auto capitalization`; - createNotification({ - text, - type: "success" - }); - } catch (err) { - console.error(err); - createNotification({ - text: "Failed to update auto capitalization", - type: "error" - }); - } + const text = `Successfully ${state ? "enabled" : "disabled"} auto capitalization`; + createNotification({ + text, + type: "success" + }); }; return ( diff --git a/frontend/src/pages/secret-manager/SettingsPage/components/BackfillSecretReferenceSection/BackfillSecretReferenceSection.tsx b/frontend/src/pages/secret-manager/SettingsPage/components/BackfillSecretReferenceSection/BackfillSecretReferenceSection.tsx index 26f5c7fc9..9350698dc 100644 --- a/frontend/src/pages/secret-manager/SettingsPage/components/BackfillSecretReferenceSection/BackfillSecretReferenceSection.tsx +++ b/frontend/src/pages/secret-manager/SettingsPage/components/BackfillSecretReferenceSection/BackfillSecretReferenceSection.tsx @@ -13,12 +13,8 @@ export const BackfillSecretReferenceSecretion = () => { const handleBackfill = async () => { if (backfillSecretReferences.isPending) return; - try { - await backfillSecretReferences.mutateAsync({ projectId: currentProject.id || "" }); - createNotification({ text: "Successfully re-indexed secret references", type: "success" }); - } catch { - createNotification({ text: "Failed to re-index secret references", type: "error" }); - } + await backfillSecretReferences.mutateAsync({ projectId: currentProject.id || "" }); + createNotification({ text: "Successfully re-indexed secret references", type: "success" }); }; const isAdmin = hasProjectRole(ProjectMembershipRole.Admin); diff --git a/frontend/src/pages/secret-manager/SettingsPage/components/EncryptionTab/EncryptionTab.tsx b/frontend/src/pages/secret-manager/SettingsPage/components/EncryptionTab/EncryptionTab.tsx index 9e4627d26..e22719c83 100644 --- a/frontend/src/pages/secret-manager/SettingsPage/components/EncryptionTab/EncryptionTab.tsx +++ b/frontend/src/pages/secret-manager/SettingsPage/components/EncryptionTab/EncryptionTab.tsx @@ -124,17 +124,13 @@ const LoadBackupModal = ({ return; } - try { - await loadKmsBackup(backupContent); - createNotification({ - text: "Successfully loaded KMS backup", - type: "success" - }); + await loadKmsBackup(backupContent); + createNotification({ + text: "Successfully loaded KMS backup", + type: "success" + }); - onOpenChange(false); - } catch (err) { - console.error(err); - } + onOpenChange(false); }; const parseFile = (file?: File) => { @@ -245,20 +241,16 @@ export const EncryptionTab = () => { }); const onUpdateProjectKms = async (data: TForm) => { - try { - await updateProjectKms( - data.kmsKeyId === INTERNAL_KMS_KEY_ID - ? { type: KmsType.Internal } - : { type: KmsType.External, kmsId: data.kmsKeyId } - ); + await updateProjectKms( + data.kmsKeyId === INTERNAL_KMS_KEY_ID + ? { type: KmsType.Internal } + : { type: KmsType.External, kmsId: data.kmsKeyId } + ); - createNotification({ - text: "Successfully updated project KMS", - type: "success" - }); - } catch (err) { - console.error(err); - } + createNotification({ + text: "Successfully updated project KMS", + type: "success" + }); }; return ( diff --git a/frontend/src/pages/secret-manager/SettingsPage/components/EnvironmentSection/AddEnvironmentModal.tsx b/frontend/src/pages/secret-manager/SettingsPage/components/EnvironmentSection/AddEnvironmentModal.tsx index 611504a14..70c486616 100644 --- a/frontend/src/pages/secret-manager/SettingsPage/components/EnvironmentSection/AddEnvironmentModal.tsx +++ b/frontend/src/pages/secret-manager/SettingsPage/components/EnvironmentSection/AddEnvironmentModal.tsx @@ -36,28 +36,20 @@ const Content = ({ onComplete }: ContentProps) => { }); const onFormSubmit = async ({ environmentName, environmentSlug }: FormData) => { - try { - if (!currentProject?.id) return; + if (!currentProject?.id) return; - const env = await mutateAsync({ - projectId: currentProject.id, - name: environmentName, - slug: environmentSlug - }); + const env = await mutateAsync({ + projectId: currentProject.id, + name: environmentName, + slug: environmentSlug + }); - createNotification({ - text: "Successfully created environment", - type: "success" - }); + createNotification({ + text: "Successfully created environment", + type: "success" + }); - onComplete(env); - } catch (err) { - console.error(err); - createNotification({ - text: "Failed to create environment", - type: "error" - }); - } + onComplete(env); }; return ( diff --git a/frontend/src/pages/secret-manager/SettingsPage/components/EnvironmentSection/EnvironmentSection.tsx b/frontend/src/pages/secret-manager/SettingsPage/components/EnvironmentSection/EnvironmentSection.tsx index 09ea16f7f..b6276a8c0 100644 --- a/frontend/src/pages/secret-manager/SettingsPage/components/EnvironmentSection/EnvironmentSection.tsx +++ b/frontend/src/pages/secret-manager/SettingsPage/components/EnvironmentSection/EnvironmentSection.tsx @@ -39,27 +39,19 @@ export const EnvironmentSection = () => { ] as const); const onEnvDeleteSubmit = async (id: string) => { - try { - if (!currentProject?.id) return; + if (!currentProject?.id) return; - await deleteWsEnvironment.mutateAsync({ - projectId: currentProject.id, - id - }); + await deleteWsEnvironment.mutateAsync({ + projectId: currentProject.id, + id + }); - createNotification({ - text: "Successfully deleted environment", - type: "success" - }); + createNotification({ + text: "Successfully deleted environment", + type: "success" + }); - handlePopUpClose("deleteEnv"); - } catch (err) { - console.error(err); - createNotification({ - text: "Failed to delete environment", - type: "error" - }); - } + handlePopUpClose("deleteEnv"); }; return ( diff --git a/frontend/src/pages/secret-manager/SettingsPage/components/EnvironmentSection/EnvironmentTable.tsx b/frontend/src/pages/secret-manager/SettingsPage/components/EnvironmentSection/EnvironmentTable.tsx index 0908d8377..6b5b3a8d2 100644 --- a/frontend/src/pages/secret-manager/SettingsPage/components/EnvironmentSection/EnvironmentTable.tsx +++ b/frontend/src/pages/secret-manager/SettingsPage/components/EnvironmentSection/EnvironmentTable.tsx @@ -46,26 +46,18 @@ export const EnvironmentTable = ({ handlePopUpOpen }: Props) => { const updateEnvironment = useUpdateWsEnvironment(); const handleReorderEnv = async (id: string, position: number) => { - try { - if (!currentProject?.id) return; + if (!currentProject?.id) return; - await updateEnvironment.mutateAsync({ - projectId: currentProject.id, - id, - position - }); + await updateEnvironment.mutateAsync({ + projectId: currentProject.id, + id, + position + }); - createNotification({ - text: "Successfully re-ordered environments", - type: "success" - }); - } catch (err) { - console.error(err); - createNotification({ - text: "Failed to re-order environments", - type: "error" - }); - } + createNotification({ + text: "Successfully re-ordered environments", + type: "success" + }); }; const isMoreEnvironmentsAllowed = diff --git a/frontend/src/pages/secret-manager/SettingsPage/components/EnvironmentSection/UpdateEnvironmentModal.tsx b/frontend/src/pages/secret-manager/SettingsPage/components/EnvironmentSection/UpdateEnvironmentModal.tsx index e2d64ee72..1c9d09101 100644 --- a/frontend/src/pages/secret-manager/SettingsPage/components/EnvironmentSection/UpdateEnvironmentModal.tsx +++ b/frontend/src/pages/secret-manager/SettingsPage/components/EnvironmentSection/UpdateEnvironmentModal.tsx @@ -33,29 +33,21 @@ export const UpdateEnvironmentModal = ({ popUp, handlePopUpClose, handlePopUpTog const oldEnvId = (popUp?.updateEnv?.data as { id: string })?.id; const onFormSubmit = async ({ name, slug }: FormData) => { - try { - if (!currentProject?.id) return; + if (!currentProject?.id) return; - await mutateAsync({ - projectId: currentProject.id, - name, - slug, - id: oldEnvId - }); + await mutateAsync({ + projectId: currentProject.id, + name, + slug, + id: oldEnvId + }); - createNotification({ - text: "Successfully updated environment", - type: "success" - }); + createNotification({ + text: "Successfully updated environment", + type: "success" + }); - handlePopUpClose("updateEnv"); - } catch (err) { - console.error(err); - createNotification({ - text: "Failed to update environment", - type: "error" - }); - } + handlePopUpClose("updateEnv"); }; return ( diff --git a/frontend/src/pages/secret-manager/SettingsPage/components/PointInTimeVersionLimitSection/PointInTimeVersionLimitSection.tsx b/frontend/src/pages/secret-manager/SettingsPage/components/PointInTimeVersionLimitSection/PointInTimeVersionLimitSection.tsx index e647ff481..6345301a0 100644 --- a/frontend/src/pages/secret-manager/SettingsPage/components/PointInTimeVersionLimitSection/PointInTimeVersionLimitSection.tsx +++ b/frontend/src/pages/secret-manager/SettingsPage/components/PointInTimeVersionLimitSection/PointInTimeVersionLimitSection.tsx @@ -34,22 +34,15 @@ export const PointInTimeVersionLimitSection = () => { if (!currentProject) return null; const handleVersionLimitSubmit = async ({ pitVersionLimit }: TForm) => { - try { - await updateProject({ - pitVersionLimit, - projectId - }); + await updateProject({ + pitVersionLimit, + projectId + }); - createNotification({ - text: "Successfully updated version limit", - type: "success" - }); - } catch { - createNotification({ - text: "Failed updating project's version limit", - type: "error" - }); - } + createNotification({ + text: "Successfully updated version limit", + type: "success" + }); }; const isAdmin = hasProjectRole(ProjectMembershipRole.Admin); diff --git a/frontend/src/pages/secret-manager/SettingsPage/components/SecretDetectionIgnoreValuesSection/SecretDetectionIgnoreValuesSection.tsx b/frontend/src/pages/secret-manager/SettingsPage/components/SecretDetectionIgnoreValuesSection/SecretDetectionIgnoreValuesSection.tsx index e086834a1..5667afa76 100644 --- a/frontend/src/pages/secret-manager/SettingsPage/components/SecretDetectionIgnoreValuesSection/SecretDetectionIgnoreValuesSection.tsx +++ b/frontend/src/pages/secret-manager/SettingsPage/components/SecretDetectionIgnoreValuesSection/SecretDetectionIgnoreValuesSection.tsx @@ -55,22 +55,15 @@ export const SecretDetectionIgnoreValuesSection = () => { }, [currentProject?.secretDetectionIgnoreValues, reset]); const handleIgnoreValuesSubmit = async ({ ignoreValues }: TForm) => { - try { - await updateProject({ - projectId: currentProject.id, - secretDetectionIgnoreValues: ignoreValues.map((item) => item.value) - }); + await updateProject({ + projectId: currentProject.id, + secretDetectionIgnoreValues: ignoreValues.map((item) => item.value) + }); - createNotification({ - text: "Successfully updated secret detection ignore values", - type: "success" - }); - } catch { - createNotification({ - text: "Failed updating secret detection ignore values", - type: "error" - }); - } + createNotification({ + text: "Successfully updated secret detection ignore values", + type: "success" + }); }; const isAdmin = hasProjectRole(ProjectMembershipRole.Admin); diff --git a/frontend/src/pages/secret-manager/SettingsPage/components/SecretSharingSection/SecretSharingSection.tsx b/frontend/src/pages/secret-manager/SettingsPage/components/SecretSharingSection/SecretSharingSection.tsx index bd8928823..ac1f735f9 100644 --- a/frontend/src/pages/secret-manager/SettingsPage/components/SecretSharingSection/SecretSharingSection.tsx +++ b/frontend/src/pages/secret-manager/SettingsPage/components/SecretSharingSection/SecretSharingSection.tsx @@ -15,12 +15,12 @@ export const SecretSharingSection = () => { const handleToggle = async (state: boolean) => { setIsLoading(true); - try { - if (!currentProject?.id) { - setIsLoading(false); - return; - } + if (!currentProject?.id) { + setIsLoading(false); + return; + } + try { await updateProject({ projectId: currentProject.id, secretSharing: state @@ -30,12 +30,6 @@ export const SecretSharingSection = () => { text: `Successfully ${state ? "enabled" : "disabled"} secret sharing for this project`, type: "success" }); - } catch (err) { - console.error(err); - createNotification({ - text: "Failed to update secret sharing for this project", - type: "error" - }); } finally { setIsLoading(false); } diff --git a/frontend/src/pages/secret-manager/SettingsPage/components/SecretSnapshotsLegacySection/SecretSnapshotsLegacySection.tsx b/frontend/src/pages/secret-manager/SettingsPage/components/SecretSnapshotsLegacySection/SecretSnapshotsLegacySection.tsx index 553f17d54..466b950f1 100644 --- a/frontend/src/pages/secret-manager/SettingsPage/components/SecretSnapshotsLegacySection/SecretSnapshotsLegacySection.tsx +++ b/frontend/src/pages/secret-manager/SettingsPage/components/SecretSnapshotsLegacySection/SecretSnapshotsLegacySection.tsx @@ -30,12 +30,6 @@ export const SecretSnapshotsLegacySection = () => { text: `Successfully ${state ? "enabled" : "disabled"} secret snapshots legacy for this project`, type: "success" }); - } catch (err) { - console.error(err); - createNotification({ - text: "Failed to update secret snapshots legacy for this project", - type: "error" - }); } finally { setIsLoading(false); } diff --git a/frontend/src/pages/secret-manager/SettingsPage/components/SecretTagsSection/AddSecretTagModal.tsx b/frontend/src/pages/secret-manager/SettingsPage/components/SecretTagsSection/AddSecretTagModal.tsx index 1d4c8e492..cfe7dff8e 100644 --- a/frontend/src/pages/secret-manager/SettingsPage/components/SecretTagsSection/AddSecretTagModal.tsx +++ b/frontend/src/pages/secret-manager/SettingsPage/components/SecretTagsSection/AddSecretTagModal.tsx @@ -39,29 +39,21 @@ export const AddSecretTagModal = ({ popUp, handlePopUpClose, handlePopUpToggle } }); const onFormSubmit = async ({ slug }: FormData) => { - try { - if (!currentProject?.id) return; + if (!currentProject?.id) return; - await createWsTag.mutateAsync({ - projectId: currentProject?.id, - tagSlug: slug, - tagColor: "" - }); + await createWsTag.mutateAsync({ + projectId: currentProject?.id, + tagSlug: slug, + tagColor: "" + }); - handlePopUpClose("CreateSecretTag"); + handlePopUpClose("CreateSecretTag"); - createNotification({ - text: "Successfully created a tag", - type: "success" - }); - reset(); - } catch (err) { - console.error(err); - createNotification({ - text: "Failed to create a tag", - type: "error" - }); - } + createNotification({ + text: "Successfully created a tag", + type: "success" + }); + reset(); }; return ( diff --git a/frontend/src/pages/secret-manager/SettingsPage/components/SecretTagsSection/SecretTagsSection.tsx b/frontend/src/pages/secret-manager/SettingsPage/components/SecretTagsSection/SecretTagsSection.tsx index 508ef2867..2964467ad 100644 --- a/frontend/src/pages/secret-manager/SettingsPage/components/SecretTagsSection/SecretTagsSection.tsx +++ b/frontend/src/pages/secret-manager/SettingsPage/components/SecretTagsSection/SecretTagsSection.tsx @@ -29,25 +29,17 @@ export const SecretTagsSection = (): JSX.Element => { const deleteWsTag = useDeleteWsTag(); const onDeleteApproved = async () => { - try { - await deleteWsTag.mutateAsync({ - projectId: currentProject?.id || "", - tagID: (popUp?.deleteTagConfirmation?.data as DeleteModalData)?.id - }); + await deleteWsTag.mutateAsync({ + projectId: currentProject?.id || "", + tagID: (popUp?.deleteTagConfirmation?.data as DeleteModalData)?.id + }); - createNotification({ - text: "Successfully deleted tag", - type: "success" - }); + createNotification({ + text: "Successfully deleted tag", + type: "success" + }); - handlePopUpClose("deleteTagConfirmation"); - } catch (err) { - console.error(err); - createNotification({ - text: "Failed to delete the tag", - type: "error" - }); - } + handlePopUpClose("deleteTagConfirmation"); }; return ( diff --git a/frontend/src/pages/secret-manager/SettingsPage/components/WebhooksTab/WebhooksTab.tsx b/frontend/src/pages/secret-manager/SettingsPage/components/WebhooksTab/WebhooksTab.tsx index 517f9e624..5296bc4ad 100644 --- a/frontend/src/pages/secret-manager/SettingsPage/components/WebhooksTab/WebhooksTab.tsx +++ b/frontend/src/pages/secret-manager/SettingsPage/components/WebhooksTab/WebhooksTab.tsx @@ -59,83 +59,51 @@ export const WebhooksTab = withProjectPermission( const { mutateAsync: deleteWebhook } = useDeleteWebhook(); const handleWebhookCreate = async (data: TFormSchema) => { - try { - await createWebhook({ - ...data, - projectId - }); - handlePopUpClose("addWebhook"); - createNotification({ - type: "success", - text: "Successfully created webhook" - }); - } catch (err) { - console.log(err); - createNotification({ - type: "error", - text: "Failed to create webhook" - }); - } + await createWebhook({ + ...data, + projectId + }); + handlePopUpClose("addWebhook"); + createNotification({ + type: "success", + text: "Successfully created webhook" + }); }; const handleWebhookDisable = async (webhookId: string, isDisabled: boolean) => { - try { - await updateWebhook({ - webhookId, - projectId, - isDisabled - }); - createNotification({ - type: "success", - text: "Successfully updated webhook" - }); - } catch (err) { - console.log(err); - createNotification({ - type: "error", - text: "Failed to update webhook" - }); - } + await updateWebhook({ + webhookId, + projectId, + isDisabled + }); + createNotification({ + type: "success", + text: "Successfully updated webhook" + }); }; const handleWebhookDelete = async () => { - try { - const webhookId = popUp?.deleteWebhook?.data as string; - await deleteWebhook({ - webhookId, - projectId - }); - handlePopUpClose("deleteWebhook"); - createNotification({ - type: "success", - text: "Successfully deleted webhook" - }); - } catch (err) { - console.log(err); - createNotification({ - type: "error", - text: "Failed to delete webhook" - }); - } + const webhookId = popUp?.deleteWebhook?.data as string; + await deleteWebhook({ + webhookId, + projectId + }); + handlePopUpClose("deleteWebhook"); + createNotification({ + type: "success", + text: "Successfully deleted webhook" + }); }; const handleWebhookTest = async (webhookId: string) => { - try { - await testWebhook({ - webhookId, - projectId - }); - createNotification({ - type: "success", - text: "Successfully triggered webhook" - }); - } catch (err) { - console.log(err); - createNotification({ - type: "error", - text: "Failed to trigger webhook" - }); - } + await testWebhook({ + webhookId, + projectId + }); + createNotification({ + type: "success", + text: "Successfully triggered webhook" + }); }; return ( diff --git a/frontend/src/pages/secret-manager/SettingsPage/components/WorkflowIntegrationSection/components/MicrosoftTeamsIntegrationForm.tsx b/frontend/src/pages/secret-manager/SettingsPage/components/WorkflowIntegrationSection/components/MicrosoftTeamsIntegrationForm.tsx index c638b65a7..707322264 100644 --- a/frontend/src/pages/secret-manager/SettingsPage/components/WorkflowIntegrationSection/components/MicrosoftTeamsIntegrationForm.tsx +++ b/frontend/src/pages/secret-manager/SettingsPage/components/WorkflowIntegrationSection/components/MicrosoftTeamsIntegrationForm.tsx @@ -130,37 +130,30 @@ export const MicrosoftTeamsIntegrationForm = ({ onClose }: Props) => { }); const handleIntegrationSave = async (data: TMicrosoftTeamsConfigForm) => { - try { - if (!currentProject) { - return; - } - - await updateProjectMicrosoftTeamsConfig({ - projectId: currentProject.id, - isAccessRequestNotificationEnabled: data.isAccessRequestNotificationEnabled, - isSecretRequestNotificationEnabled: data.isSecretRequestNotificationEnabled, - ...(data.isAccessRequestNotificationEnabled && { - accessRequestChannels: data.accessRequestChannels - }), - ...(data.isSecretRequestNotificationEnabled && { - secretRequestChannels: data.secretRequestChannels - }), - integration: WorkflowIntegrationPlatform.MICROSOFT_TEAMS, - integrationId: data.microsoftTeamsIntegrationId - }); - - createNotification({ - type: "success", - text: "Successfully created microsoft teams integration" - }); - - onClose(); - } catch { - createNotification({ - type: "error", - text: "Failed to create microsoft teams integration" - }); + if (!currentProject) { + return; } + + await updateProjectMicrosoftTeamsConfig({ + projectId: currentProject.id, + isAccessRequestNotificationEnabled: data.isAccessRequestNotificationEnabled, + isSecretRequestNotificationEnabled: data.isSecretRequestNotificationEnabled, + ...(data.isAccessRequestNotificationEnabled && { + accessRequestChannels: data.accessRequestChannels + }), + ...(data.isSecretRequestNotificationEnabled && { + secretRequestChannels: data.secretRequestChannels + }), + integration: WorkflowIntegrationPlatform.MICROSOFT_TEAMS, + integrationId: data.microsoftTeamsIntegrationId + }); + + createNotification({ + type: "success", + text: "Successfully created microsoft teams integration" + }); + + onClose(); }; const selectedAccessRequestTeamId = watch("accessRequestChannels.teamId"); diff --git a/frontend/src/pages/secret-manager/SettingsPage/components/WorkflowIntegrationSection/components/SlackIntegrationForm.tsx b/frontend/src/pages/secret-manager/SettingsPage/components/WorkflowIntegrationSection/components/SlackIntegrationForm.tsx index cf5113fad..a473e897e 100644 --- a/frontend/src/pages/secret-manager/SettingsPage/components/WorkflowIntegrationSection/components/SlackIntegrationForm.tsx +++ b/frontend/src/pages/secret-manager/SettingsPage/components/WorkflowIntegrationSection/components/SlackIntegrationForm.tsx @@ -143,33 +143,26 @@ export const SlackIntegrationForm = ({ onClose }: Props) => { }); const handleIntegrationSave = async (data: TSlackConfigForm) => { - try { - if (!currentProject) { - return; - } - - await updateProjectSlackConfig({ - ...data, - projectId: currentProject.id, - integration: WorkflowIntegrationPlatform.SLACK, - integrationId: data.slackIntegrationId, - accessRequestChannels: data.accessRequestChannels.filter(Boolean).join(", "), - secretRequestChannels: data.secretRequestChannels.filter(Boolean).join(", "), - secretSyncErrorChannels: data.secretSyncErrorChannels.filter(Boolean).join(", ") - }); - - createNotification({ - type: "success", - text: "Successfully created slack integration" - }); - - onClose(); - } catch { - createNotification({ - type: "error", - text: "Failed to create slack integration" - }); + if (!currentProject) { + return; } + + await updateProjectSlackConfig({ + ...data, + projectId: currentProject.id, + integration: WorkflowIntegrationPlatform.SLACK, + integrationId: data.slackIntegrationId, + accessRequestChannels: data.accessRequestChannels.filter(Boolean).join(", "), + secretRequestChannels: data.secretRequestChannels.filter(Boolean).join(", "), + secretSyncErrorChannels: data.secretSyncErrorChannels.filter(Boolean).join(", ") + }); + + createNotification({ + type: "success", + text: "Successfully created slack integration" + }); + + onClose(); }; const secretRequestNotifState = watch("isSecretRequestNotificationEnabled"); diff --git a/frontend/src/pages/secret-manager/integrations/BitbucketConfigurePage/BitbucketConfigurePage.tsx b/frontend/src/pages/secret-manager/integrations/BitbucketConfigurePage/BitbucketConfigurePage.tsx index 8d855f284..b66644bdc 100644 --- a/frontend/src/pages/secret-manager/integrations/BitbucketConfigurePage/BitbucketConfigurePage.tsx +++ b/frontend/src/pages/secret-manager/integrations/BitbucketConfigurePage/BitbucketConfigurePage.tsx @@ -126,43 +126,35 @@ export const BitbucketConfigurePage = () => { }: TFormData) => { if (!targetRepo || !targetWorkspace) return; - try { - await createIntegration.mutateAsync({ - integrationAuthId, - isActive: true, - app: targetRepo.name, - appId: targetRepo.appId, - sourceEnvironment: sourceEnvironment.slug, - targetEnvironment: targetWorkspace.name, - targetEnvironmentId: targetWorkspace.slug, - ...(scope.value === BitbucketScope.Env && - targetEnvironment && { - targetService: targetEnvironment.name, - targetServiceId: targetEnvironment.uuid - }), - secretPath - }); + await createIntegration.mutateAsync({ + integrationAuthId, + isActive: true, + app: targetRepo.name, + appId: targetRepo.appId, + sourceEnvironment: sourceEnvironment.slug, + targetEnvironment: targetWorkspace.name, + targetEnvironmentId: targetWorkspace.slug, + ...(scope.value === BitbucketScope.Env && + targetEnvironment && { + targetService: targetEnvironment.name, + targetServiceId: targetEnvironment.uuid + }), + secretPath + }); - createNotification({ - type: "success", - text: "Successfully created integration" - }); - navigate({ - to: "/projects/secret-management/$projectId/integrations", - params: { - projectId: currentProject.id - }, - search: { - selectedTab: IntegrationsListPageTabs.NativeIntegrations - } - }); - } catch (err) { - createNotification({ - type: "error", - text: "Failed to create integration" - }); - console.error(err); - } + createNotification({ + type: "success", + text: "Successfully created integration" + }); + navigate({ + to: "/projects/secret-management/$projectId/integrations", + params: { + projectId: currentProject.id + }, + search: { + selectedTab: IntegrationsListPageTabs.NativeIntegrations + } + }); }; useEffect(() => { diff --git a/frontend/src/pages/secret-manager/integrations/CircleCIConfigurePage/CircleCIConfigurePage.tsx b/frontend/src/pages/secret-manager/integrations/CircleCIConfigurePage/CircleCIConfigurePage.tsx index 7df2ae35c..a7ecbca6a 100644 --- a/frontend/src/pages/secret-manager/integrations/CircleCIConfigurePage/CircleCIConfigurePage.tsx +++ b/frontend/src/pages/secret-manager/integrations/CircleCIConfigurePage/CircleCIConfigurePage.tsx @@ -73,51 +73,43 @@ export const CircleCIConfigurePage = () => { : undefined; const onSubmit = async (data: TFormData) => { - try { - if (data.scope === CircleCiScope.Context) { - await mutateAsync({ - scope: data.scope, - integrationAuthId, - isActive: true, - sourceEnvironment: data.sourceEnvironment.slug, - app: data.targetContext.name, - appId: data.targetContext.id, - owner: data.targetOrg.name, - secretPath: data.secretPath - }); - } else { - await mutateAsync({ - scope: data.scope, - integrationAuthId, - isActive: true, - app: data.targetProject.name, // project name - owner: data.targetOrg.name, // organization name - appId: data.targetProject.id, // project id (used for syncing) - sourceEnvironment: data.sourceEnvironment.slug, - secretPath: data.secretPath - }); - } - - createNotification({ - type: "success", - text: "Successfully created integration" + if (data.scope === CircleCiScope.Context) { + await mutateAsync({ + scope: data.scope, + integrationAuthId, + isActive: true, + sourceEnvironment: data.sourceEnvironment.slug, + app: data.targetContext.name, + appId: data.targetContext.id, + owner: data.targetOrg.name, + secretPath: data.secretPath }); - navigate({ - to: "/projects/secret-management/$projectId/integrations", - params: { - projectId: currentProject.id - }, - search: { - selectedTab: IntegrationsListPageTabs.NativeIntegrations - } + } else { + await mutateAsync({ + scope: data.scope, + integrationAuthId, + isActive: true, + app: data.targetProject.name, // project name + owner: data.targetOrg.name, // organization name + appId: data.targetProject.id, // project id (used for syncing) + sourceEnvironment: data.sourceEnvironment.slug, + secretPath: data.secretPath }); - } catch (err) { - createNotification({ - type: "error", - text: "Failed to create integration" - }); - console.error(err); } + + createNotification({ + type: "success", + text: "Successfully created integration" + }); + navigate({ + to: "/projects/secret-management/$projectId/integrations", + params: { + projectId: currentProject.id + }, + search: { + selectedTab: IntegrationsListPageTabs.NativeIntegrations + } + }); }; if (isCircleCIOrganizationsLoading) diff --git a/frontend/src/pages/secret-manager/integrations/CloudflarePagesConfigurePage/CloudflarePagesConfigurePage.tsx b/frontend/src/pages/secret-manager/integrations/CloudflarePagesConfigurePage/CloudflarePagesConfigurePage.tsx index 0a0d08863..3948351c3 100644 --- a/frontend/src/pages/secret-manager/integrations/CloudflarePagesConfigurePage/CloudflarePagesConfigurePage.tsx +++ b/frontend/src/pages/secret-manager/integrations/CloudflarePagesConfigurePage/CloudflarePagesConfigurePage.tsx @@ -1,8 +1,6 @@ import { useEffect, useState } from "react"; import { useNavigate, useSearch } from "@tanstack/react-router"; -import axios from "axios"; -import { createNotification } from "@app/components/notifications"; import { Button, Card, @@ -102,19 +100,7 @@ export const CloudflarePagesConfigurePage = () => { selectedTab: IntegrationsListPageTabs.NativeIntegrations } }); - } catch (err) { - console.error(err); - - let errorMessage: string = "Something went wrong!"; - if (axios.isAxiosError(err)) { - const { message } = err?.response?.data as { message: string }; - errorMessage = message; - } - - createNotification({ - text: errorMessage, - type: "error" - }); + } catch { setIsLoading(false); } }; diff --git a/frontend/src/pages/secret-manager/integrations/CloudflareWorkersConfigurePage/CloudflareWorkersConfigurePage.tsx b/frontend/src/pages/secret-manager/integrations/CloudflareWorkersConfigurePage/CloudflareWorkersConfigurePage.tsx index 58bc8596b..417f0fe84 100644 --- a/frontend/src/pages/secret-manager/integrations/CloudflareWorkersConfigurePage/CloudflareWorkersConfigurePage.tsx +++ b/frontend/src/pages/secret-manager/integrations/CloudflareWorkersConfigurePage/CloudflareWorkersConfigurePage.tsx @@ -1,8 +1,6 @@ import { useEffect, useState } from "react"; import { useNavigate, useSearch } from "@tanstack/react-router"; -import axios from "axios"; -import { createNotification } from "@app/components/notifications"; import { Button, Card, CardTitle, FormControl, Select, SelectItem } from "@app/components/v2"; import { SecretPathInput } from "@app/components/v2/SecretPathInput"; import { ROUTE_PATHS } from "@app/const/routes"; @@ -75,19 +73,7 @@ export const CloudflareWorkersConfigurePage = () => { selectedTab: IntegrationsListPageTabs.NativeIntegrations } }); - } catch (err) { - console.error(err); - - let errorMessage: string = "Something went wrong!"; - if (axios.isAxiosError(err)) { - const { message } = err?.response?.data as { message: string }; - errorMessage = message; - } - - createNotification({ - text: errorMessage, - type: "error" - }); + } catch { setIsLoading(false); } }; diff --git a/frontend/src/pages/secret-manager/integrations/DatabricksConfigurePage/DatabricksConfigurePage.tsx b/frontend/src/pages/secret-manager/integrations/DatabricksConfigurePage/DatabricksConfigurePage.tsx index 1f5a3c40a..05c943fc5 100644 --- a/frontend/src/pages/secret-manager/integrations/DatabricksConfigurePage/DatabricksConfigurePage.tsx +++ b/frontend/src/pages/secret-manager/integrations/DatabricksConfigurePage/DatabricksConfigurePage.tsx @@ -55,49 +55,45 @@ export const DatabricksConfigurePage = () => { const [secretPath, setSecretPath] = useState("/"); const handleButtonClick = async () => { - try { - if (!integrationAuth?.id) return; + if (!integrationAuth?.id) return; - if (!targetScope) { - createNotification({ - type: "error", - text: "Please select a scope" - }); - return; - } - - const selectedScope = integrationAuthScopes?.find( - (integrationAuthScope) => integrationAuthScope.name === targetScope - ); - - if (!selectedScope) { - createNotification({ - type: "error", - text: "Invalid scope selected" - }); - return; - } - - await mutateAsync({ - integrationAuthId: integrationAuth?.id, - isActive: true, - app: selectedScope.name, // scope name - sourceEnvironment: selectedSourceEnvironment, - secretPath + if (!targetScope) { + createNotification({ + type: "error", + text: "Please select a scope" }); - - navigate({ - to: "/projects/secret-management/$projectId/integrations", - params: { - projectId: currentProject.id - }, - search: { - selectedTab: IntegrationsListPageTabs.NativeIntegrations - } - }); - } catch (err) { - console.error(err); + return; } + + const selectedScope = integrationAuthScopes?.find( + (integrationAuthScope) => integrationAuthScope.name === targetScope + ); + + if (!selectedScope) { + createNotification({ + type: "error", + text: "Invalid scope selected" + }); + return; + } + + await mutateAsync({ + integrationAuthId: integrationAuth?.id, + isActive: true, + app: selectedScope.name, // scope name + sourceEnvironment: selectedSourceEnvironment, + secretPath + }); + + navigate({ + to: "/projects/secret-management/$projectId/integrations", + params: { + projectId: currentProject.id + }, + search: { + selectedTab: IntegrationsListPageTabs.NativeIntegrations + } + }); }; return integrationAuth && selectedSourceEnvironment && integrationAuthScopes ? ( diff --git a/frontend/src/pages/secret-manager/integrations/GithubConfigurePage/GithubConfigurePage.tsx b/frontend/src/pages/secret-manager/integrations/GithubConfigurePage/GithubConfigurePage.tsx index 5e9871ade..741c03032 100644 --- a/frontend/src/pages/secret-manager/integrations/GithubConfigurePage/GithubConfigurePage.tsx +++ b/frontend/src/pages/secret-manager/integrations/GithubConfigurePage/GithubConfigurePage.tsx @@ -12,12 +12,10 @@ import { import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { zodResolver } from "@hookform/resolvers/zod"; import { useNavigate, useSearch } from "@tanstack/react-router"; -import axios from "axios"; import { motion } from "framer-motion"; import { twMerge } from "tailwind-merge"; import { z, ZodIssueCode } from "zod"; -import { createNotification } from "@app/components/notifications"; import { Button, Card, @@ -275,19 +273,7 @@ export const GithubConfigurePage = () => { selectedTab: IntegrationsListPageTabs.NativeIntegrations } }); - } catch (err) { - console.error(err); - - let errorMessage: string = "Something went wrong!"; - if (axios.isAxiosError(err)) { - const { message } = err?.response?.data as { message: string }; - errorMessage = message; - } - - createNotification({ - text: errorMessage, - type: "error" - }); + } catch { setIsLoading(false); } }; diff --git a/frontend/src/pages/secret-manager/integrations/HashicorpVaultAuthorizePage/HashicorpVaultAuthorizePage.tsx b/frontend/src/pages/secret-manager/integrations/HashicorpVaultAuthorizePage/HashicorpVaultAuthorizePage.tsx index 4b922a9bc..93d892241 100644 --- a/frontend/src/pages/secret-manager/integrations/HashicorpVaultAuthorizePage/HashicorpVaultAuthorizePage.tsx +++ b/frontend/src/pages/secret-manager/integrations/HashicorpVaultAuthorizePage/HashicorpVaultAuthorizePage.tsx @@ -4,10 +4,8 @@ import { faArrowUpRightFromSquare, faBookOpen } from "@fortawesome/free-solid-sv import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { zodResolver } from "@hookform/resolvers/zod"; import { useNavigate } from "@tanstack/react-router"; -import axios from "axios"; import { z } from "zod"; -import { createNotification } from "@app/components/notifications"; import { Button, Card, CardBody, CardTitle, FormControl, Input } from "@app/components/v2"; import { useProject } from "@app/context"; import { useSaveIntegrationAccessToken } from "@app/hooks/api"; @@ -41,37 +39,23 @@ export const HashicorpVaultAuthorizePage = () => { }); const handleFormSubmit = async (formData: TForm) => { - try { - const integrationAuth = await mutateAsync({ - workspaceId: currentProject.id, - integration: "hashicorp-vault", - accessId: formData.vaultRoleID, - accessToken: formData.vaultSecretID, - url: formData.vaultURL, - namespace: formData.vaultNamespace - }); - navigate({ - to: "/projects/secret-management/$projectId/integrations/hashicorp-vault/create", - params: { - projectId: currentProject.id - }, - search: { - integrationAuthId: integrationAuth.id - } - }); - } catch (err) { - console.error(err); - let errorMessage: string = "Something went wrong!"; - if (axios.isAxiosError(err)) { - const { message } = err?.response?.data as { message: string }; - errorMessage = message; + const integrationAuth = await mutateAsync({ + workspaceId: currentProject.id, + integration: "hashicorp-vault", + accessId: formData.vaultRoleID, + accessToken: formData.vaultSecretID, + url: formData.vaultURL, + namespace: formData.vaultNamespace + }); + navigate({ + to: "/projects/secret-management/$projectId/integrations/hashicorp-vault/create", + params: { + projectId: currentProject.id + }, + search: { + integrationAuthId: integrationAuth.id } - - createNotification({ - text: errorMessage, - type: "error" - }); - } + }); }; return ( diff --git a/frontend/src/pages/secret-manager/integrations/HashicorpVaultConfigurePage/HashicorpVaultConfigurePage.tsx b/frontend/src/pages/secret-manager/integrations/HashicorpVaultConfigurePage/HashicorpVaultConfigurePage.tsx index 0dfcbb0bf..0636625df 100644 --- a/frontend/src/pages/secret-manager/integrations/HashicorpVaultConfigurePage/HashicorpVaultConfigurePage.tsx +++ b/frontend/src/pages/secret-manager/integrations/HashicorpVaultConfigurePage/HashicorpVaultConfigurePage.tsx @@ -10,10 +10,8 @@ import { import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { zodResolver } from "@hookform/resolvers/zod"; import { useNavigate, useSearch } from "@tanstack/react-router"; -import axios from "axios"; import { z } from "zod"; -import { createNotification } from "@app/components/notifications"; import { Button, Card, @@ -90,38 +88,24 @@ export const HashicorpVaultConfigurePage = () => { }); const handleFormSubmit = async (formData: TForm) => { - try { - if (!integrationAuth?.id) return; - await mutateAsync({ - integrationAuthId: integrationAuth?.id, - isActive: true, - app: formData.vaultEnginePath, - sourceEnvironment: formData.selectedSourceEnvironment, - path: formData.vaultSecretPath, - secretPath: formData.secretPath - }); - navigate({ - to: "/projects/secret-management/$projectId/integrations", - params: { - projectId: currentProject.id - }, - search: { - selectedTab: IntegrationsListPageTabs.NativeIntegrations - } - }); - } catch (err) { - console.error(err); - let errorMessage: string = "Something went wrong!"; - if (axios.isAxiosError(err)) { - const { message } = err?.response?.data as { message: string }; - errorMessage = message; + if (!integrationAuth?.id) return; + await mutateAsync({ + integrationAuthId: integrationAuth?.id, + isActive: true, + app: formData.vaultEnginePath, + sourceEnvironment: formData.selectedSourceEnvironment, + path: formData.vaultSecretPath, + secretPath: formData.secretPath + }); + navigate({ + to: "/projects/secret-management/$projectId/integrations", + params: { + projectId: currentProject.id + }, + search: { + selectedTab: IntegrationsListPageTabs.NativeIntegrations } - - createNotification({ - text: errorMessage, - type: "error" - }); - } + }); }; return integrationAuth ? ( diff --git a/frontend/src/pages/secret-manager/integrations/OctopusDeployAuthorizePage/OctopusDeployAuthorizePage.tsx b/frontend/src/pages/secret-manager/integrations/OctopusDeployAuthorizePage/OctopusDeployAuthorizePage.tsx index 21851e4cd..9e50fd43d 100644 --- a/frontend/src/pages/secret-manager/integrations/OctopusDeployAuthorizePage/OctopusDeployAuthorizePage.tsx +++ b/frontend/src/pages/secret-manager/integrations/OctopusDeployAuthorizePage/OctopusDeployAuthorizePage.tsx @@ -6,7 +6,6 @@ import { zodResolver } from "@hookform/resolvers/zod"; import { useNavigate } from "@tanstack/react-router"; import { z } from "zod"; -import { createNotification } from "@app/components/notifications"; import { Button, Card, CardTitle, FormControl, Input } from "@app/components/v2"; import { useProject } from "@app/context"; import { removeTrailingSlash } from "@app/helpers/string"; @@ -29,30 +28,22 @@ export const OctopusDeployAuthorizePage = () => { }); const onSubmit = async ({ instanceUrl, apiKey }: TForm) => { - try { - const integrationAuth = await mutateAsync({ - workspaceId: currentProject.id, - integration: "octopus-deploy", - url: removeTrailingSlash(instanceUrl), - accessToken: apiKey - }); + const integrationAuth = await mutateAsync({ + workspaceId: currentProject.id, + integration: "octopus-deploy", + url: removeTrailingSlash(instanceUrl), + accessToken: apiKey + }); - navigate({ - to: "/projects/secret-management/$projectId/integrations/octopus-deploy/create", - params: { - projectId: currentProject.id - }, - search: { - integrationAuthId: integrationAuth.id - } - }); - } catch (err: any) { - createNotification({ - type: "error", - text: err.message ?? "Error authorizing integration" - }); - console.error(err); - } + navigate({ + to: "/projects/secret-management/$projectId/integrations/octopus-deploy/create", + params: { + projectId: currentProject.id + }, + search: { + integrationAuthId: integrationAuth.id + } + }); }; return ( diff --git a/frontend/src/pages/secret-manager/integrations/OctopusDeployConfigurePage/OctopusDeployConfigurePage.tsx b/frontend/src/pages/secret-manager/integrations/OctopusDeployConfigurePage/OctopusDeployConfigurePage.tsx index 5b531ac2d..75f8f5031 100644 --- a/frontend/src/pages/secret-manager/integrations/OctopusDeployConfigurePage/OctopusDeployConfigurePage.tsx +++ b/frontend/src/pages/secret-manager/integrations/OctopusDeployConfigurePage/OctopusDeployConfigurePage.tsx @@ -107,49 +107,41 @@ export const OctopusDeployConfigurePage = () => { targetRoles, scope }: TFormData) => { - try { - await createIntegration.mutateAsync({ - integrationAuthId, - isActive: true, - scope, - app: targetResource.name, - appId: targetResource.appId, - targetEnvironment: targetSpace.Name, - targetEnvironmentId: targetSpace.Id, - metadata: { - octopusDeployScopeValues: { - Environment: targetEnvironments?.map(({ Id }) => Id), - Action: targetActions?.map(({ Id }) => Id), - Channel: targetChannels?.map(({ Id }) => Id), - ProcessOwner: targetProcesses?.map(({ Id }) => Id), - Role: targetRoles?.map(({ Id }) => Id), - Machine: targetMachines?.map(({ Id }) => Id) - } - }, - sourceEnvironment: sourceEnvironment.slug, - secretPath - }); - - createNotification({ - type: "success", - text: "Successfully created integration" - }); - navigate({ - to: "/projects/secret-management/$projectId/integrations", - params: { - projectId: currentProject.id - }, - search: { - selectedTab: IntegrationsListPageTabs.NativeIntegrations + await createIntegration.mutateAsync({ + integrationAuthId, + isActive: true, + scope, + app: targetResource.name, + appId: targetResource.appId, + targetEnvironment: targetSpace.Name, + targetEnvironmentId: targetSpace.Id, + metadata: { + octopusDeployScopeValues: { + Environment: targetEnvironments?.map(({ Id }) => Id), + Action: targetActions?.map(({ Id }) => Id), + Channel: targetChannels?.map(({ Id }) => Id), + ProcessOwner: targetProcesses?.map(({ Id }) => Id), + Role: targetRoles?.map(({ Id }) => Id), + Machine: targetMachines?.map(({ Id }) => Id) } - }); - } catch (err) { - createNotification({ - type: "error", - text: "Failed to create integration" - }); - console.error(err); - } + }, + sourceEnvironment: sourceEnvironment.slug, + secretPath + }); + + createNotification({ + type: "success", + text: "Successfully created integration" + }); + navigate({ + to: "/projects/secret-management/$projectId/integrations", + params: { + projectId: currentProject.id + }, + search: { + selectedTab: IntegrationsListPageTabs.NativeIntegrations + } + }); }; useEffect(() => { diff --git a/frontend/src/pages/secret-scanning/SecretScanningDataSourceByIdPage/components/SecretScanningResourceRow.tsx b/frontend/src/pages/secret-scanning/SecretScanningDataSourceByIdPage/components/SecretScanningResourceRow.tsx index 740cf6d71..b2021bf5c 100644 --- a/frontend/src/pages/secret-scanning/SecretScanningDataSourceByIdPage/components/SecretScanningResourceRow.tsx +++ b/frontend/src/pages/secret-scanning/SecretScanningDataSourceByIdPage/components/SecretScanningResourceRow.tsx @@ -81,24 +81,17 @@ export const SecretScanningResourceRow = ({ resource, dataSource }: Props) => { const navigate = useNavigate(); const handleTriggerScan = async () => { - try { - await triggerDataSourceScan.mutateAsync({ - dataSourceId: dataSource.id, - type: dataSource.type, - projectId: dataSource.projectId, - resourceId: id - }); + await triggerDataSourceScan.mutateAsync({ + dataSourceId: dataSource.id, + type: dataSource.type, + projectId: dataSource.projectId, + resourceId: id + }); - createNotification({ - text: `Successfully triggered scan for ${name}`, - type: "success" - }); - } catch { - createNotification({ - text: `Failed to trigger scan for ${name}`, - type: "error" - }); - } + createNotification({ + text: `Successfully triggered scan for ${name}`, + type: "success" + }); }; const [isIdCopied, setIsIdCopied] = useToggle(false); diff --git a/frontend/src/pages/secret-scanning/SecretScanningDataSourceByIdPage/components/SecretScanningResourceSection.tsx b/frontend/src/pages/secret-scanning/SecretScanningDataSourceByIdPage/components/SecretScanningResourceSection.tsx index 5616c956a..1e81357b8 100644 --- a/frontend/src/pages/secret-scanning/SecretScanningDataSourceByIdPage/components/SecretScanningResourceSection.tsx +++ b/frontend/src/pages/secret-scanning/SecretScanningDataSourceByIdPage/components/SecretScanningResourceSection.tsx @@ -22,23 +22,16 @@ export const SecretScanningResourceSection = ({ dataSource }: Props) => { const triggerDataSourceScan = useTriggerSecretScanningDataSource(); const handleTriggerScan = async () => { - try { - await triggerDataSourceScan.mutateAsync({ - dataSourceId: dataSource.id, - type: dataSource.type, - projectId: dataSource.projectId - }); + await triggerDataSourceScan.mutateAsync({ + dataSourceId: dataSource.id, + type: dataSource.type, + projectId: dataSource.projectId + }); - createNotification({ - text: `Successfully triggered scan for ${dataSource.name}`, - type: "success" - }); - } catch { - createNotification({ - text: `Failed to trigger scan for ${dataSource.name}`, - type: "error" - }); - } + createNotification({ + text: `Successfully triggered scan for ${dataSource.name}`, + type: "success" + }); }; const resourceDetails = RESOURCE_DESCRIPTION_HELPER[dataSource.type]; diff --git a/frontend/src/pages/secret-scanning/SecretScanningDataSourcesPage/components/SecretScanningDataSourcesTable.tsx b/frontend/src/pages/secret-scanning/SecretScanningDataSourcesPage/components/SecretScanningDataSourcesTable.tsx index 8e879acce..ac61c8f54 100644 --- a/frontend/src/pages/secret-scanning/SecretScanningDataSourcesPage/components/SecretScanningDataSourcesTable.tsx +++ b/frontend/src/pages/secret-scanning/SecretScanningDataSourcesPage/components/SecretScanningDataSourcesTable.tsx @@ -184,44 +184,30 @@ export const SecretScanningDataSourcesTable = ({ dataSources }: Props) => { const isAutoScanEnabled = !dataSource.isAutoScanEnabled; - try { - await updateDataSource.mutateAsync({ - dataSourceId: dataSource.id, - type: dataSource.type, - isAutoScanEnabled, - projectId: dataSource.projectId - }); + await updateDataSource.mutateAsync({ + dataSourceId: dataSource.id, + type: dataSource.type, + isAutoScanEnabled, + projectId: dataSource.projectId + }); - createNotification({ - text: `Successfully ${isAutoScanEnabled ? "enabled" : "disabled"} auto-scan for ${destinationName} Data Source`, - type: "success" - }); - } catch { - createNotification({ - text: `Failed to ${isAutoScanEnabled ? "enable" : "disable"} auto-scan for ${destinationName} Data Source`, - type: "error" - }); - } + createNotification({ + text: `Successfully ${isAutoScanEnabled ? "enabled" : "disabled"} auto-scan for ${destinationName} Data Source`, + type: "success" + }); }; const handleTriggerScan = async (dataSource: TSecretScanningDataSource) => { - try { - await triggerDataSourceScan.mutateAsync({ - dataSourceId: dataSource.id, - type: dataSource.type, - projectId: dataSource.projectId - }); + await triggerDataSourceScan.mutateAsync({ + dataSourceId: dataSource.id, + type: dataSource.type, + projectId: dataSource.projectId + }); - createNotification({ - text: "Successfully triggered scan", - type: "success" - }); - } catch { - createNotification({ - text: "Failed to trigger scan", - type: "error" - }); - } + createNotification({ + text: "Successfully triggered scan", + type: "success" + }); }; return ( diff --git a/frontend/src/pages/secret-scanning/SecretScanningFindingsPage/components/SecretScanningUpdateFindingModal.tsx b/frontend/src/pages/secret-scanning/SecretScanningFindingsPage/components/SecretScanningUpdateFindingModal.tsx index 484cbcf36..c4838673b 100644 --- a/frontend/src/pages/secret-scanning/SecretScanningFindingsPage/components/SecretScanningUpdateFindingModal.tsx +++ b/frontend/src/pages/secret-scanning/SecretScanningFindingsPage/components/SecretScanningUpdateFindingModal.tsx @@ -55,39 +55,32 @@ const Content = ({ findings, onComplete }: ContentProps) => { const onSubmit = async (data: FormType) => { if (!data.status) return; - try { - if (findings.length > 1) { - await updateMultipleFindings.mutateAsync( - findings.map((f) => ({ - ...data, - status: data.status!, - findingId: f.id, - projectId: f.projectId - })) - ); - } else { - await updateMultipleFindings.mutateAsync([ - { - ...data, - status: data.status, - findingId: findings[0].id, - projectId: findings[0].projectId - } - ]); - } - - createNotification({ - type: "success", - text: `Finding status${single ? "" : "es"} successfully updated` - }); - - onComplete(); - } catch { - createNotification({ - type: "error", - text: `Failed to update finding status${single ? "" : "es"}` - }); + if (findings.length > 1) { + await updateMultipleFindings.mutateAsync( + findings.map((f) => ({ + ...data, + status: data.status!, + findingId: f.id, + projectId: f.projectId + })) + ); + } else { + await updateMultipleFindings.mutateAsync([ + { + ...data, + status: data.status, + findingId: findings[0].id, + projectId: findings[0].projectId + } + ]); } + + createNotification({ + type: "success", + text: `Finding status${single ? "" : "es"} successfully updated` + }); + + onComplete(); }; return ( diff --git a/frontend/src/pages/secret-scanning/SettingsPage/components/ProjectScanningConfigTab/SecretScanningConfigForm.tsx b/frontend/src/pages/secret-scanning/SettingsPage/components/ProjectScanningConfigTab/SecretScanningConfigForm.tsx index c9df333c4..7ff36964d 100644 --- a/frontend/src/pages/secret-scanning/SettingsPage/components/ProjectScanningConfigTab/SecretScanningConfigForm.tsx +++ b/frontend/src/pages/secret-scanning/SettingsPage/components/ProjectScanningConfigTab/SecretScanningConfigForm.tsx @@ -38,22 +38,15 @@ export const SecretScanningConfigForm = ({ config }: Props) => { }); const onSubmit = async ({ content }: FormType) => { - try { - await updateConfig.mutateAsync({ - projectId: config.projectId, - content: content || null - }); + await updateConfig.mutateAsync({ + projectId: config.projectId, + content: content || null + }); - createNotification({ - type: "success", - text: "Configuration successfully updated" - }); - } catch { - createNotification({ - type: "error", - text: "Failed to update Configuration" - }); - } + createNotification({ + type: "success", + text: "Configuration successfully updated" + }); }; return ( diff --git a/frontend/src/pages/ssh/SettingsPage/components/ProjectSshTab/components/ProjectSshConfigCasSection.tsx b/frontend/src/pages/ssh/SettingsPage/components/ProjectSshTab/components/ProjectSshConfigCasSection.tsx index 86bdf3c34..aed25d46f 100644 --- a/frontend/src/pages/ssh/SettingsPage/components/ProjectSshTab/components/ProjectSshConfigCasSection.tsx +++ b/frontend/src/pages/ssh/SettingsPage/components/ProjectSshTab/components/ProjectSshConfigCasSection.tsx @@ -47,24 +47,16 @@ export const ProjectSshConfigCasSection = () => { }, [sshConfig]); const onFormSubmit = async ({ defaultUserSshCaId, defaultHostSshCaId }: FormData) => { - try { - await updateProjectSshConfig({ - projectId: currentProject.id, - defaultUserSshCaId: defaultUserSshCaId || undefined, - defaultHostSshCaId: defaultHostSshCaId || undefined - }); + await updateProjectSshConfig({ + projectId: currentProject.id, + defaultUserSshCaId: defaultUserSshCaId || undefined, + defaultHostSshCaId: defaultHostSshCaId || undefined + }); - createNotification({ - text: "Successfully updated SSH project settings", - type: "success" - }); - } catch (err) { - console.error(err); - createNotification({ - text: "Failed to update SSH project settings", - type: "error" - }); - } + createNotification({ + text: "Successfully updated SSH project settings", + type: "success" + }); }; return ( diff --git a/frontend/src/pages/ssh/SshCaByIDPage/SshCaByIDPage.tsx b/frontend/src/pages/ssh/SshCaByIDPage/SshCaByIDPage.tsx index bb6790a92..41a69a7bd 100644 --- a/frontend/src/pages/ssh/SshCaByIDPage/SshCaByIDPage.tsx +++ b/frontend/src/pages/ssh/SshCaByIDPage/SshCaByIDPage.tsx @@ -43,30 +43,22 @@ const Page = () => { ] as const); const onRemoveCaSubmit = async (caIdToDelete: string) => { - try { - if (!projectId) return; + if (!projectId) return; - await deleteSshCa({ caId: caIdToDelete }); + await deleteSshCa({ caId: caIdToDelete }); - createNotification({ - text: "Successfully deleted SSH CA", - type: "success" - }); + createNotification({ + text: "Successfully deleted SSH CA", + type: "success" + }); - handlePopUpClose("deleteSshCa"); - navigate({ - to: "/projects/ssh/$projectId/overview", - params: { - projectId - } - }); - } catch (err) { - console.error(err); - createNotification({ - text: "Failed to delete SSH CA", - type: "error" - }); - } + handlePopUpClose("deleteSshCa"); + navigate({ + to: "/projects/ssh/$projectId/overview", + params: { + projectId + } + }); }; return ( diff --git a/frontend/src/pages/ssh/SshCaByIDPage/components/SshCertificateModal.tsx b/frontend/src/pages/ssh/SshCaByIDPage/components/SshCertificateModal.tsx index 6e0baa502..32470308a 100644 --- a/frontend/src/pages/ssh/SshCaByIDPage/components/SshCertificateModal.tsx +++ b/frontend/src/pages/ssh/SshCaByIDPage/components/SshCertificateModal.tsx @@ -122,65 +122,57 @@ export const SshCertificateModal = ({ popUp, handlePopUpToggle }: Props) => { ttl, keyId }: FormData) => { - try { - if (!templateData) return; - if (!projectId) return; + if (!templateData) return; + if (!projectId) return; - switch (operation) { - case SshCertificateOperation.SIGN_SSH_KEY: { - const { serialNumber, signedKey } = await signSshKey({ - projectId, - certificateTemplateId: templateData.id, - publicKey: existingPublicKey, - certType, - principals: principals.split(",").map((user) => user.trim()), - ttl, - keyId - }); + switch (operation) { + case SshCertificateOperation.SIGN_SSH_KEY: { + const { serialNumber, signedKey } = await signSshKey({ + projectId, + certificateTemplateId: templateData.id, + publicKey: existingPublicKey, + certType, + principals: principals.split(",").map((user) => user.trim()), + ttl, + keyId + }); - setCertificateDetails({ - serialNumber, - signedKey - }); - break; - } - case SshCertificateOperation.ISSUE_SSH_CREDS: { - const { serialNumber, publicKey, privateKey, signedKey } = await issueSshCreds({ - projectId, - certificateTemplateId: templateData.id, - keyAlgorithm, - certType, - principals: principals.split(",").map((user) => user.trim()), - ttl, - keyId - }); - - setCertificateDetails({ - serialNumber, - privateKey, - publicKey, - signedKey - }); - break; - } - default: { - break; - } + setCertificateDetails({ + serialNumber, + signedKey + }); + break; } + case SshCertificateOperation.ISSUE_SSH_CREDS: { + const { serialNumber, publicKey, privateKey, signedKey } = await issueSshCreds({ + projectId, + certificateTemplateId: templateData.id, + keyAlgorithm, + certType, + principals: principals.split(",").map((user) => user.trim()), + ttl, + keyId + }); - reset(); - - createNotification({ - text: "Successfully created SSH certificate", - type: "success" - }); - } catch (err) { - console.error(err); - createNotification({ - text: "Failed to create SSH certificate", - type: "error" - }); + setCertificateDetails({ + serialNumber, + privateKey, + publicKey, + signedKey + }); + break; + } + default: { + break; + } } + + reset(); + + createNotification({ + text: "Successfully created SSH certificate", + type: "success" + }); }; return ( diff --git a/frontend/src/pages/ssh/SshCaByIDPage/components/SshCertificateTemplateModal.tsx b/frontend/src/pages/ssh/SshCaByIDPage/components/SshCertificateTemplateModal.tsx index 17c7a552e..926a1d022 100644 --- a/frontend/src/pages/ssh/SshCaByIDPage/components/SshCertificateTemplateModal.tsx +++ b/frontend/src/pages/ssh/SshCaByIDPage/components/SshCertificateTemplateModal.tsx @@ -138,52 +138,44 @@ export const SshCertificateTemplateModal = ({ popUp, handlePopUpToggle, sshCaId allowedHosts, allowCustomKeyIds }: FormData) => { - try { - if (certTemplate) { - await updateSshCertTemplate({ - id: certTemplate.id, - name, - ttl, - maxTTL, - allowedUsers: allowedUsers ? allowedUsers.split(",").map((user) => user.trim()) : [], - allowedHosts: allowedHosts ? allowedHosts.split(",").map((host) => host.trim()) : [], - allowUserCertificates, - allowHostCertificates, - allowCustomKeyIds - }); + if (certTemplate) { + await updateSshCertTemplate({ + id: certTemplate.id, + name, + ttl, + maxTTL, + allowedUsers: allowedUsers ? allowedUsers.split(",").map((user) => user.trim()) : [], + allowedHosts: allowedHosts ? allowedHosts.split(",").map((host) => host.trim()) : [], + allowUserCertificates, + allowHostCertificates, + allowCustomKeyIds + }); - createNotification({ - text: "Successfully updated SSH certificate template", - type: "success" - }); - } else { - await createSshCertTemplate({ - sshCaId, - name, - ttl, - maxTTL, - allowedUsers: allowedUsers ? allowedUsers.split(",").map((user) => user.trim()) : [], - allowedHosts: allowedHosts ? allowedHosts.split(",").map((host) => host.trim()) : [], - allowUserCertificates, - allowHostCertificates, - allowCustomKeyIds - }); - - createNotification({ - text: "Successfully created SSH certificate template", - type: "success" - }); - } - - reset(); - handlePopUpToggle("sshCertificateTemplate", false); - } catch (err) { - console.error(err); createNotification({ - text: "Failed to save changes", - type: "error" + text: "Successfully updated SSH certificate template", + type: "success" + }); + } else { + await createSshCertTemplate({ + sshCaId, + name, + ttl, + maxTTL, + allowedUsers: allowedUsers ? allowedUsers.split(",").map((user) => user.trim()) : [], + allowedHosts: allowedHosts ? allowedHosts.split(",").map((host) => host.trim()) : [], + allowUserCertificates, + allowHostCertificates, + allowCustomKeyIds + }); + + createNotification({ + text: "Successfully created SSH certificate template", + type: "success" }); } + + reset(); + handlePopUpToggle("sshCertificateTemplate", false); }; return ( diff --git a/frontend/src/pages/ssh/SshCaByIDPage/components/SshCertificateTemplatesSection.tsx b/frontend/src/pages/ssh/SshCaByIDPage/components/SshCertificateTemplatesSection.tsx index 792c6ad3b..5b021715f 100644 --- a/frontend/src/pages/ssh/SshCaByIDPage/components/SshCertificateTemplatesSection.tsx +++ b/frontend/src/pages/ssh/SshCaByIDPage/components/SshCertificateTemplatesSection.tsx @@ -33,24 +33,16 @@ export const SshCertificateTemplatesSection = ({ caId }: Props) => { const { mutateAsync: updateSshCertTemplate } = useUpdateSshCertTemplate(); const onRemoveSshCertificateTemplateSubmit = async (id: string) => { - try { - await deleteSshCertTemplate({ - id - }); + await deleteSshCertTemplate({ + id + }); - await createNotification({ - text: "Successfully deleted SSH certificate template", - type: "success" - }); + createNotification({ + text: "Successfully deleted SSH certificate template", + type: "success" + }); - handlePopUpClose("deleteSshCertificateTemplate"); - } catch (err) { - console.error(err); - createNotification({ - text: "Failed to delete SSH certificate template", - type: "error" - }); - } + handlePopUpClose("deleteSshCertificateTemplate"); }; const onUpdateSshCaStatus = async ({ @@ -60,26 +52,16 @@ export const SshCertificateTemplatesSection = ({ caId }: Props) => { templateId: string; status: SshCertTemplateStatus; }) => { - try { - await updateSshCertTemplate({ id: templateId, status }); + await updateSshCertTemplate({ id: templateId, status }); - await createNotification({ - text: `Successfully ${ - status === SshCertTemplateStatus.ACTIVE ? "enabled" : "disabled" - } SSH certificate template`, - type: "success" - }); + createNotification({ + text: `Successfully ${ + status === SshCertTemplateStatus.ACTIVE ? "enabled" : "disabled" + } SSH certificate template`, + type: "success" + }); - handlePopUpClose("sshCertificateTemplateStatus"); - } catch (err) { - console.error(err); - createNotification({ - text: `Failed to ${ - status === SshCertTemplateStatus.ACTIVE ? "enabled" : "disabled" - } SSH certificate template`, - type: "error" - }); - } + handlePopUpClose("sshCertificateTemplateStatus"); }; return ( diff --git a/frontend/src/pages/ssh/SshCasPage/components/SshCaModal.tsx b/frontend/src/pages/ssh/SshCasPage/components/SshCaModal.tsx index 4c8ce4e19..53e0298ff 100644 --- a/frontend/src/pages/ssh/SshCasPage/components/SshCaModal.tsx +++ b/frontend/src/pages/ssh/SshCasPage/components/SshCaModal.tsx @@ -106,47 +106,39 @@ export const SshCaModal = ({ popUp, handlePopUpToggle }: Props) => { publicKey, privateKey }: FormData) => { - try { - if (!projectId) return; + if (!projectId) return; - if (ca) { - await updateMutateAsync({ - caId: ca.id, - friendlyName - }); - } else { - const { id: newCaId } = await createMutateAsync({ - projectId, - friendlyName, - keySource, - keyAlgorithm, - publicKey, - privateKey - }); - - navigate({ - to: "/projects/ssh/$projectId/ca/$caId", - params: { - projectId, - caId: newCaId - } - }); - } - - reset(); - handlePopUpToggle("sshCa", false); - - createNotification({ - text: `Successfully ${ca ? "updated" : "created"} SSH CA`, - type: "success" + if (ca) { + await updateMutateAsync({ + caId: ca.id, + friendlyName }); - } catch (err) { - console.error(err); - createNotification({ - text: `Failed to ${ca ? "update" : "create"} SSH CA`, - type: "error" + } else { + const { id: newCaId } = await createMutateAsync({ + projectId, + friendlyName, + keySource, + keyAlgorithm, + publicKey, + privateKey + }); + + navigate({ + to: "/projects/ssh/$projectId/ca/$caId", + params: { + projectId, + caId: newCaId + } }); } + + reset(); + handlePopUpToggle("sshCa", false); + + createNotification({ + text: `Successfully ${ca ? "updated" : "created"} SSH CA`, + type: "success" + }); }; return ( diff --git a/frontend/src/pages/ssh/SshCasPage/components/SshCaSection.tsx b/frontend/src/pages/ssh/SshCasPage/components/SshCaSection.tsx index 016dc1306..11942795c 100644 --- a/frontend/src/pages/ssh/SshCasPage/components/SshCaSection.tsx +++ b/frontend/src/pages/ssh/SshCasPage/components/SshCaSection.tsx @@ -22,41 +22,25 @@ export const SshCaSection = () => { ] as const); const onRemoveSshCaSubmit = async (caId: string) => { - try { - await deleteSshCa({ caId }); + await deleteSshCa({ caId }); - createNotification({ - text: "Successfully deleted SSH CA", - type: "success" - }); + createNotification({ + text: "Successfully deleted SSH CA", + type: "success" + }); - handlePopUpClose("deleteSshCa"); - } catch (err) { - console.error(err); - createNotification({ - text: "Failed to delete SSH CA", - type: "error" - }); - } + handlePopUpClose("deleteSshCa"); }; const onUpdateSshCaStatus = async ({ caId, status }: { caId: string; status: SshCaStatus }) => { - try { - await updateSshCa({ caId, status }); + await updateSshCa({ caId, status }); - createNotification({ - text: `Successfully ${status === SshCaStatus.ACTIVE ? "enabled" : "disabled"} SSH CA`, - type: "success" - }); + createNotification({ + text: `Successfully ${status === SshCaStatus.ACTIVE ? "enabled" : "disabled"} SSH CA`, + type: "success" + }); - handlePopUpClose("sshCaStatus"); - } catch (err) { - console.error(err); - createNotification({ - text: `Failed to ${status === SshCaStatus.ACTIVE ? "enabled" : "disabled"} SSH CA`, - type: "error" - }); - } + handlePopUpClose("sshCaStatus"); }; return ( diff --git a/frontend/src/pages/ssh/SshHostGroupDetailsByIDPage/SshHostGroupDetailsByIDPage.tsx b/frontend/src/pages/ssh/SshHostGroupDetailsByIDPage/SshHostGroupDetailsByIDPage.tsx index d093003ac..ffb596ac2 100644 --- a/frontend/src/pages/ssh/SshHostGroupDetailsByIDPage/SshHostGroupDetailsByIDPage.tsx +++ b/frontend/src/pages/ssh/SshHostGroupDetailsByIDPage/SshHostGroupDetailsByIDPage.tsx @@ -44,30 +44,22 @@ const Page = () => { ] as const); const onRemoveSshGroupSubmit = async (groupIdToDelete: string) => { - try { - if (!projectId) return; + if (!projectId) return; - await deleteSshHostGroup({ sshHostGroupId: groupIdToDelete }); + await deleteSshHostGroup({ sshHostGroupId: groupIdToDelete }); - createNotification({ - text: "Successfully deleted SSH group", - type: "success" - }); + createNotification({ + text: "Successfully deleted SSH group", + type: "success" + }); - handlePopUpClose("deleteSshHostGroup"); - navigate({ - to: "/projects/ssh/$projectId/overview", - params: { - projectId - } - }); - } catch (err) { - console.error(err); - createNotification({ - text: "Failed to delete SSH group", - type: "error" - }); - } + handlePopUpClose("deleteSshHostGroup"); + navigate({ + to: "/projects/ssh/$projectId/overview", + params: { + projectId + } + }); }; return ( diff --git a/frontend/src/pages/ssh/SshHostGroupDetailsByIDPage/components/AddHostGroupMemberModal.tsx b/frontend/src/pages/ssh/SshHostGroupDetailsByIDPage/components/AddHostGroupMemberModal.tsx index 2374492a5..e45266fa0 100644 --- a/frontend/src/pages/ssh/SshHostGroupDetailsByIDPage/components/AddHostGroupMemberModal.tsx +++ b/frontend/src/pages/ssh/SshHostGroupDetailsByIDPage/components/AddHostGroupMemberModal.tsx @@ -42,30 +42,23 @@ export const AddHostGroupMemberModal = ({ popUp, handlePopUpToggle }: Props) => useAddHostToSshHostGroup(); const handleAddHost = async (sshHostId: string) => { - try { - if (!popUpData?.sshHostGroupId) { - createNotification({ - text: "Some data is missing, please refresh the page and try again", - type: "error" - }); - return; - } - - await addHostToSshHostGroup({ - sshHostGroupId: popUpData.sshHostGroupId, - sshHostId - }); - + if (!popUpData?.sshHostGroupId) { createNotification({ - text: "Successfully added host to the group", - type: "success" - }); - } catch { - createNotification({ - text: "Failed to add host to the group", + text: "Some data is missing, please refresh the page and try again", type: "error" }); + return; } + + await addHostToSshHostGroup({ + sshHostGroupId: popUpData.sshHostGroupId, + sshHostId + }); + + createNotification({ + text: "Successfully added host to the group", + type: "success" + }); }; return ( diff --git a/frontend/src/pages/ssh/SshHostGroupDetailsByIDPage/components/SshHostGroupHostsSection.tsx b/frontend/src/pages/ssh/SshHostGroupDetailsByIDPage/components/SshHostGroupHostsSection.tsx index 6f45fe510..189ec6e56 100644 --- a/frontend/src/pages/ssh/SshHostGroupDetailsByIDPage/components/SshHostGroupHostsSection.tsx +++ b/frontend/src/pages/ssh/SshHostGroupDetailsByIDPage/components/SshHostGroupHostsSection.tsx @@ -40,25 +40,17 @@ export const SshHostGroupHostsSection = ({ sshHostGroupId }: Props) => { }; const onRemoveSshHostSubmit = async (sshHostId: string) => { - try { - await removeHostFromGroup({ - sshHostId, - sshHostGroupId - }); + await removeHostFromGroup({ + sshHostId, + sshHostGroupId + }); - await createNotification({ - text: "Successfully removed host from SSH group", - type: "success" - }); + createNotification({ + text: "Successfully removed host from SSH group", + type: "success" + }); - handlePopUpClose("removeHostFromSshHostGroup"); - } catch (err) { - console.error(err); - createNotification({ - text: "Failed to remove host from SSH group", - type: "error" - }); - } + handlePopUpClose("removeHostFromSshHostGroup"); }; return ( diff --git a/frontend/src/pages/ssh/SshHostsPage/components/SshHostGroupModal.tsx b/frontend/src/pages/ssh/SshHostsPage/components/SshHostGroupModal.tsx index 6e65dd532..d7411f889 100644 --- a/frontend/src/pages/ssh/SshHostsPage/components/SshHostGroupModal.tsx +++ b/frontend/src/pages/ssh/SshHostsPage/components/SshHostGroupModal.tsx @@ -121,67 +121,59 @@ export const SshHostGroupModal = ({ popUp, handlePopUpToggle }: Props) => { }, [sshHostGroup]); const onFormSubmit = async ({ name, loginMappings }: FormData) => { - try { - if (!projectId) return; + if (!projectId) return; - // check if there is already a different host group with the same name - const existingNames = - sshHostGroups?.filter((h) => h.id !== sshHostGroup?.id).map((h) => h.name) || []; - - if (existingNames.includes(name.trim())) { - createNotification({ - text: "A host group with this name already exists.", - type: "error" - }); - return; - } - - const transformedLoginMappings = loginMappings.map(({ loginUser, allowedPrincipals }) => { - const usernames = allowedPrincipals - .filter((p) => p.type === "user" && p.value) - .map((p) => p.value); - - const groupNames = allowedPrincipals - .filter((p) => p.type === "group" && p.value) - .map((p) => p.value); - - return { - loginUser, - allowedPrincipals: { - usernames, - groups: groupNames - } - }; - }); - - if (sshHostGroup) { - await updateMutateAsync({ - sshHostGroupId: sshHostGroup.id, - name, - loginMappings: transformedLoginMappings - }); - } else { - await createMutateAsync({ - projectId, - name, - loginMappings: transformedLoginMappings - }); - } - - reset(); - handlePopUpToggle("sshHostGroup", false); + // check if there is already a different host group with the same name + const existingNames = + sshHostGroups?.filter((h) => h.id !== sshHostGroup?.id).map((h) => h.name) || []; + if (existingNames.includes(name.trim())) { createNotification({ - text: `Successfully ${sshHostGroup ? "updated" : "created"} SSH host group`, - type: "success" - }); - } catch (err) { - console.error(err); - createNotification({ - text: `Failed to ${sshHostGroup ? "update" : "create"} SSH host group`, + text: "A host group with this name already exists.", type: "error" }); + return; } + + const transformedLoginMappings = loginMappings.map(({ loginUser, allowedPrincipals }) => { + const usernames = allowedPrincipals + .filter((p) => p.type === "user" && p.value) + .map((p) => p.value); + + const groupNames = allowedPrincipals + .filter((p) => p.type === "group" && p.value) + .map((p) => p.value); + + return { + loginUser, + allowedPrincipals: { + usernames, + groups: groupNames + } + }; + }); + + if (sshHostGroup) { + await updateMutateAsync({ + sshHostGroupId: sshHostGroup.id, + name, + loginMappings: transformedLoginMappings + }); + } else { + await createMutateAsync({ + projectId, + name, + loginMappings: transformedLoginMappings + }); + } + + reset(); + handlePopUpToggle("sshHostGroup", false); + + createNotification({ + text: `Successfully ${sshHostGroup ? "updated" : "created"} SSH host group`, + type: "success" + }); }; const toggleMapping = (index: number) => { diff --git a/frontend/src/pages/ssh/SshHostsPage/components/SshHostGroupsSection.tsx b/frontend/src/pages/ssh/SshHostsPage/components/SshHostGroupsSection.tsx index efffbd3a2..5febe22b7 100644 --- a/frontend/src/pages/ssh/SshHostsPage/components/SshHostGroupsSection.tsx +++ b/frontend/src/pages/ssh/SshHostsPage/components/SshHostGroupsSection.tsx @@ -34,22 +34,14 @@ export const SshHostGroupsSection = () => { }; const onRemoveSshHostGroupSubmit = async (sshHostGroupId: string) => { - try { - const hostGroup = await deleteSshHostGroup({ sshHostGroupId }); + const hostGroup = await deleteSshHostGroup({ sshHostGroupId }); - createNotification({ - text: `Successfully deleted SSH host group: ${hostGroup.name}`, - type: "success" - }); + createNotification({ + text: `Successfully deleted SSH host group: ${hostGroup.name}`, + type: "success" + }); - handlePopUpClose("deleteSshHostGroup"); - } catch (err) { - console.error(err); - createNotification({ - text: "Failed to delete SSH host group", - type: "error" - }); - } + handlePopUpClose("deleteSshHostGroup"); }; return ( diff --git a/frontend/src/pages/ssh/SshHostsPage/components/SshHostModal.tsx b/frontend/src/pages/ssh/SshHostsPage/components/SshHostModal.tsx index e9b0d870a..afcde908f 100644 --- a/frontend/src/pages/ssh/SshHostsPage/components/SshHostModal.tsx +++ b/frontend/src/pages/ssh/SshHostsPage/components/SshHostModal.tsx @@ -140,93 +140,84 @@ export const SshHostModal = ({ popUp, handlePopUpToggle }: Props) => { }, [sshHost]); const onFormSubmit = async ({ hostname, alias, userCertTtl, loginMappings }: FormData) => { - try { - if (!projectId) return; + if (!projectId) return; - // Filter out login mappings that are from host groups - const hostLoginMappings = loginMappings.filter( - (mapping) => mapping.source === LoginMappingSource.HOST - ); + // Filter out login mappings that are from host groups + const hostLoginMappings = loginMappings.filter( + (mapping) => mapping.source === LoginMappingSource.HOST + ); - // check if there is already a different host with the same hostname - const existingHostnames = - sshHosts?.filter((h) => h.id !== sshHost?.id).map((h) => h.hostname) || []; + // check if there is already a different host with the same hostname + const existingHostnames = + sshHosts?.filter((h) => h.id !== sshHost?.id).map((h) => h.hostname) || []; - if (existingHostnames.includes(hostname.trim())) { + if (existingHostnames.includes(hostname.trim())) { + createNotification({ + text: "A host with this hostname already exists.", + type: "error" + }); + return; + } + + const trimmedAlias = alias.trim(); + + // check if there is already a different host with the same non-null alias + if (trimmedAlias) { + const existingAliases = + sshHosts?.filter((h) => h.id !== sshHost?.id && h.alias !== null).map((h) => h.alias) || []; + + if (existingAliases.includes(trimmedAlias)) { createNotification({ - text: "A host with this hostname already exists.", + text: "A host with this alias already exists.", type: "error" }); return; } + } - const trimmedAlias = alias.trim(); + const transformedLoginMappings = hostLoginMappings.map(({ loginUser, allowedPrincipals }) => { + const usernames = allowedPrincipals + .filter((p) => p.type === "user" && p.value) + .map((p) => p.value); - // check if there is already a different host with the same non-null alias - if (trimmedAlias) { - const existingAliases = - sshHosts?.filter((h) => h.id !== sshHost?.id && h.alias !== null).map((h) => h.alias) || - []; + const groupNames = allowedPrincipals + .filter((p) => p.type === "group" && p.value) + .map((p) => p.value); - if (existingAliases.includes(trimmedAlias)) { - createNotification({ - text: "A host with this alias already exists.", - type: "error" - }); - return; + return { + loginUser, + allowedPrincipals: { + usernames, + groups: groupNames } - } + }; + }); - const transformedLoginMappings = hostLoginMappings.map(({ loginUser, allowedPrincipals }) => { - const usernames = allowedPrincipals - .filter((p) => p.type === "user" && p.value) - .map((p) => p.value); - - const groupNames = allowedPrincipals - .filter((p) => p.type === "group" && p.value) - .map((p) => p.value); - - return { - loginUser, - allowedPrincipals: { - usernames, - groups: groupNames - } - }; + if (sshHost) { + await updateMutateAsync({ + sshHostId: sshHost.id, + hostname, + alias: trimmedAlias, + userCertTtl, + loginMappings: transformedLoginMappings }); - - if (sshHost) { - await updateMutateAsync({ - sshHostId: sshHost.id, - hostname, - alias: trimmedAlias, - userCertTtl, - loginMappings: transformedLoginMappings - }); - } else { - await createMutateAsync({ - projectId, - hostname, - alias: trimmedAlias, - userCertTtl, - loginMappings: transformedLoginMappings - }); - } - - reset(); - handlePopUpToggle("sshHost", false); - - createNotification({ - text: `Successfully ${sshHost ? "updated" : "added"} SSH host`, - type: "success" - }); - } catch (err) { - console.error(err); - createNotification({ - text: `Failed to ${sshHost ? "update" : "add"} SSH host`, - type: "error" + } else { + await createMutateAsync({ + projectId, + hostname, + alias: trimmedAlias, + userCertTtl, + loginMappings: transformedLoginMappings }); } + + reset(); + handlePopUpToggle("sshHost", false); + + createNotification({ + text: `Successfully ${sshHost ? "updated" : "added"} SSH host`, + type: "success" + }); }; const toggleMapping = (index: number) => { diff --git a/frontend/src/pages/ssh/SshHostsPage/components/SshHostsSection.tsx b/frontend/src/pages/ssh/SshHostsPage/components/SshHostsSection.tsx index 0f57cbeb2..53e8062ab 100644 --- a/frontend/src/pages/ssh/SshHostsPage/components/SshHostsSection.tsx +++ b/frontend/src/pages/ssh/SshHostsPage/components/SshHostsSection.tsx @@ -20,22 +20,14 @@ export const SshHostsSection = () => { ] as const); const onRemoveSshHostSubmit = async (sshHostId: string) => { - try { - const host = await deleteSshHost({ sshHostId }); + const host = await deleteSshHost({ sshHostId }); - createNotification({ - text: `Successfully deleted SSH host: ${host.hostname}`, - type: "success" - }); + createNotification({ + text: `Successfully deleted SSH host: ${host.hostname}`, + type: "success" + }); - handlePopUpClose("deleteSshHost"); - } catch (err) { - console.error(err); - createNotification({ - text: "Failed to delete SSH host", - type: "error" - }); - } + handlePopUpClose("deleteSshHost"); }; return ( diff --git a/frontend/src/pages/user/PersonalSettingsPage/components/APIKeySection/APIKeyTable.tsx b/frontend/src/pages/user/PersonalSettingsPage/components/APIKeySection/APIKeyTable.tsx index 6fe6afd43..cf2960ada 100644 --- a/frontend/src/pages/user/PersonalSettingsPage/components/APIKeySection/APIKeyTable.tsx +++ b/frontend/src/pages/user/PersonalSettingsPage/components/APIKeySection/APIKeyTable.tsx @@ -22,19 +22,11 @@ export const APIKeyTable = () => { const { mutateAsync } = useDeleteAPIKey(); const handleDeleteAPIKeyDataClick = async (apiKeyDataId: string) => { - try { - await mutateAsync(apiKeyDataId); - createNotification({ - text: "Successfully deleted API key", - type: "success" - }); - } catch (err) { - console.error(err); - createNotification({ - text: "Failed to delete API key", - type: "error" - }); - } + await mutateAsync(apiKeyDataId); + createNotification({ + text: "Successfully deleted API key", + type: "success" + }); }; return ( diff --git a/frontend/src/pages/user/PersonalSettingsPage/components/APIKeySection/AddAPIKeyModal.tsx b/frontend/src/pages/user/PersonalSettingsPage/components/APIKeySection/AddAPIKeyModal.tsx index 213479b47..f28c39339 100644 --- a/frontend/src/pages/user/PersonalSettingsPage/components/APIKeySection/AddAPIKeyModal.tsx +++ b/frontend/src/pages/user/PersonalSettingsPage/components/APIKeySection/AddAPIKeyModal.tsx @@ -76,27 +76,19 @@ export const AddAPIKeyModal = ({ popUp, handlePopUpToggle }: Props) => { }; const onFormSubmit = async ({ name, expiresIn }: FormData) => { - try { - const { apiKey } = await mutateAsync({ - name, - expiresIn: expirationMapping[expiresIn] - }); + const { apiKey } = await mutateAsync({ + name, + expiresIn: expirationMapping[expiresIn] + }); - setNewAPIKey(apiKey); + setNewAPIKey(apiKey); - createNotification({ - text: "Successfully created API key", - type: "success" - }); + createNotification({ + text: "Successfully created API key", + type: "success" + }); - reset(); - } catch (err) { - console.error(err); - createNotification({ - text: "Failed to create API key", - type: "error" - }); - } + reset(); }; const hasAPIKey = Boolean(newAPIKey); diff --git a/frontend/src/pages/user/PersonalSettingsPage/components/ChangeEmailSection/ChangeEmailSection.tsx b/frontend/src/pages/user/PersonalSettingsPage/components/ChangeEmailSection/ChangeEmailSection.tsx index c9d457e44..bd37e5620 100644 --- a/frontend/src/pages/user/PersonalSettingsPage/components/ChangeEmailSection/ChangeEmailSection.tsx +++ b/frontend/src/pages/user/PersonalSettingsPage/components/ChangeEmailSection/ChangeEmailSection.tsx @@ -83,23 +83,14 @@ export const ChangeEmailSection = () => { return; } - try { - await requestEmailChangeOTP({ newEmail }); - setPendingEmail(newEmail); - setIsOTPModalOpen(true); + await requestEmailChangeOTP({ newEmail }); + setPendingEmail(newEmail); + setIsOTPModalOpen(true); - createNotification({ - text: "Verification code sent to your new email address. Check your inbox!", - type: "success" - }); - } catch (err: any) { - console.error(err); - const errorMessage = err?.response?.data?.message || "Failed to send verification code"; - createNotification({ - text: errorMessage, - type: "error" - }); - } + createNotification({ + text: "Verification code sent to your new email address. Check your inbox!", + type: "success" + }); }; const [typedOTP, setTypedOTP] = useState(""); @@ -135,8 +126,6 @@ export const ChangeEmailSection = () => { navigate({ to: "/login" }); }, 2000); } catch (err: any) { - console.error(err); - const errorMessage = err?.response?.data?.message || "Invalid verification code"; if (errorMessage.includes("Invalid verification code")) { // Reset to email step so user must request new OTP @@ -149,11 +138,6 @@ export const ChangeEmailSection = () => { text: "Invalid verification code. Please request a new one.", type: "error" }); - } else { - createNotification({ - text: errorMessage, - type: "error" - }); } } }; diff --git a/frontend/src/pages/user/PersonalSettingsPage/components/ChangePasswordSection/ChangePasswordSection.tsx b/frontend/src/pages/user/PersonalSettingsPage/components/ChangePasswordSection/ChangePasswordSection.tsx index 552eab741..1ae492162 100644 --- a/frontend/src/pages/user/PersonalSettingsPage/components/ChangePasswordSection/ChangePasswordSection.tsx +++ b/frontend/src/pages/user/PersonalSettingsPage/components/ChangePasswordSection/ChangePasswordSection.tsx @@ -97,21 +97,13 @@ export const ChangePasswordSection = () => { }; const onSetupPassword = async () => { - try { - await sendSetupPasswordEmail.mutateAsync(); + await sendSetupPasswordEmail.mutateAsync(); - createNotification({ - title: "Password setup verification email sent", - text: "Check your email to confirm password setup", - type: "info" - }); - } catch (err) { - console.error(err); - createNotification({ - text: "Failed to send password setup email", - type: "error" - }); - } + createNotification({ + title: "Password setup verification email sent", + text: "Check your email to confirm password setup", + type: "info" + }); }; return ( diff --git a/frontend/src/pages/user/PersonalSettingsPage/components/DeleteAccountSection/DeleteAccountSection.tsx b/frontend/src/pages/user/PersonalSettingsPage/components/DeleteAccountSection/DeleteAccountSection.tsx index 5761a772a..301942346 100644 --- a/frontend/src/pages/user/PersonalSettingsPage/components/DeleteAccountSection/DeleteAccountSection.tsx +++ b/frontend/src/pages/user/PersonalSettingsPage/components/DeleteAccountSection/DeleteAccountSection.tsx @@ -15,23 +15,15 @@ export const DeleteAccountSection = () => { const { mutateAsync: deleteUserMutateAsync, isPending } = useDeleteMe(); const handleDeleteAccountSubmit = async () => { - try { - await deleteUserMutateAsync(); + await deleteUserMutateAsync(); - createNotification({ - text: "Successfully deleted account", - type: "success" - }); + createNotification({ + text: "Successfully deleted account", + type: "success" + }); - navigate({ to: "/login" }); - handlePopUpClose("deleteAccount"); - } catch (err) { - console.error(err); - createNotification({ - text: "Failed to delete account", - type: "error" - }); - } + navigate({ to: "/login" }); + handlePopUpClose("deleteAccount"); }; return ( diff --git a/frontend/src/pages/user/PersonalSettingsPage/components/SecuritySection/MFASection.tsx b/frontend/src/pages/user/PersonalSettingsPage/components/SecuritySection/MFASection.tsx index ef29f3ff6..74f4ed99b 100644 --- a/frontend/src/pages/user/PersonalSettingsPage/components/SecuritySection/MFASection.tsx +++ b/frontend/src/pages/user/PersonalSettingsPage/components/SecuritySection/MFASection.tsx @@ -84,49 +84,27 @@ export const MFASection = () => { }, [totpRegistration, showMobileAuthSetup]); const handleTotpDeletion = async () => { - try { - await deleteTotpConfiguration(); + await deleteTotpConfiguration(); - await mutateAsync({ - selectedMfaMethod: MfaMethod.EMAIL - }); + await mutateAsync({ + selectedMfaMethod: MfaMethod.EMAIL + }); - createNotification({ - text: "Successfully deleted mobile authenticator and switched to email authentication", - type: "success" - }); + createNotification({ + text: "Successfully deleted mobile authenticator and switched to email authentication", + type: "success" + }); - handlePopUpClose("deleteTotpConfig"); - } catch (err) { - console.error(err); - const error = err as any; - const text = error?.response?.data?.message ?? "Failed to delete mobile authenticator"; - - createNotification({ - text, - type: "error" - }); - } + handlePopUpClose("deleteTotpConfig"); }; const handleGenerateMoreRecoveryCodes = async () => { - try { - await createTotpRecoveryCodes(); + await createTotpRecoveryCodes(); - createNotification({ - text: "Successfully generated new recovery codes", - type: "success" - }); - } catch (err) { - console.error(err); - const error = err as any; - const text = error?.response?.data?.message ?? "Failed to generate new recovery codes"; - - createNotification({ - text, - type: "error" - }); - } + createNotification({ + text: "Successfully generated new recovery codes", + type: "success" + }); }; const handleFormDataChange = async (field: string, value: any) => { @@ -200,10 +178,6 @@ export const MFASection = () => { await queryClient.invalidateQueries({ queryKey: userKeys.totpConfiguration }); } catch { - createNotification({ - text: "Failed to verify TOTP code. Please try again.", - type: "error" - }); setIsLoading(false); return; } @@ -249,12 +223,6 @@ export const MFASection = () => { setShowMobileAuthSetup(false); setTotpCode(""); setShouldShowRecoveryCodes.off(); - } catch (err) { - createNotification({ - text: "Something went wrong while updating two-factor authentication settings.", - type: "error" - }); - console.error(err); } finally { setIsLoading(false); } diff --git a/frontend/src/pages/user/PersonalSettingsPage/components/SessionsSection/SessionsTable.tsx b/frontend/src/pages/user/PersonalSettingsPage/components/SessionsSection/SessionsTable.tsx index 027f2ed46..f37be42a1 100644 --- a/frontend/src/pages/user/PersonalSettingsPage/components/SessionsSection/SessionsTable.tsx +++ b/frontend/src/pages/user/PersonalSettingsPage/components/SessionsSection/SessionsTable.tsx @@ -40,19 +40,11 @@ export const SessionsTable = () => { ] as const); const handleSignOut = async (sessionId: string) => { - try { - await revokeMySessionById(sessionId); - createNotification({ - text: "Session revoked successfully", - type: "success" - }); - } catch (error) { - console.error(error); - createNotification({ - text: "Failed to revoke session", - type: "error" - }); - } + await revokeMySessionById(sessionId); + createNotification({ + text: "Session revoked successfully", + type: "success" + }); handlePopUpClose("deleteSession"); }; diff --git a/frontend/src/pages/user/PersonalSettingsPage/components/UserNameSection/UserNameSection.tsx b/frontend/src/pages/user/PersonalSettingsPage/components/UserNameSection/UserNameSection.tsx index df0dae9cb..1e06d298f 100644 --- a/frontend/src/pages/user/PersonalSettingsPage/components/UserNameSection/UserNameSection.tsx +++ b/frontend/src/pages/user/PersonalSettingsPage/components/UserNameSection/UserNameSection.tsx @@ -27,22 +27,14 @@ export const UserNameSection = (): JSX.Element => { }, [user]); const onFormSubmit = async ({ name }: FormData) => { - try { - if (!user?.id) return; - if (name === "") return; + if (!user?.id) return; + if (name === "") return; - await mutateAsync({ newName: name }); - createNotification({ - text: "Successfully renamed user", - type: "success" - }); - } catch (error) { - console.error(error); - createNotification({ - text: "Failed to rename user", - type: "error" - }); - } + await mutateAsync({ newName: name }); + createNotification({ + text: "Successfully renamed user", + type: "success" + }); }; return (