From 59ccabec6955a22ccd744cb3c67fdc117eb1b539 Mon Sep 17 00:00:00 2001 From: Tuan Dang Date: Tue, 9 Jul 2024 11:51:21 +0700 Subject: [PATCH] Make fixes based on review --- backend/src/server/routes/index.ts | 3 +- .../routes/v1/identity-access-token-router.ts | 35 ------ .../routes/v1/identity-token-auth-router.ts | 59 +++++++-- .../identity-access-token-service.ts | 52 +------- .../identity-access-token-types.ts | 6 - .../identity-token-auth-service.ts | 99 ++++++++++----- .../identity-token-auth-types.ts | 11 +- .../src/services/identity/identity-service.ts | 4 +- frontend/src/hooks/api/identities/index.tsx | 9 +- .../src/hooks/api/identities/mutations.tsx | 17 +-- .../views/Org/IdentityPage/IdentityPage.tsx | 11 +- .../IdentityAuthenticationSection.tsx | 12 -- .../IdentityClientSecrets.tsx | 24 +++- .../IdentityTokens.tsx | 24 ++-- .../components/IdentityDetailsSection.tsx | 26 +++- .../components/IdentityTokenModal.tsx | 4 +- .../IdentityAuthMethodModal.tsx | 113 +++++++++++++++++- .../IdentitySection/IdentityAwsAuthForm.tsx | 18 +-- .../IdentitySection/IdentityAzureAuthForm.tsx | 18 +-- .../IdentitySection/IdentityGcpAuthForm.tsx | 18 +-- .../IdentityKubernetesAuthForm.tsx | 18 +-- .../IdentitySection/IdentitySection.tsx | 6 +- .../IdentitySection/IdentityTable.tsx | 10 +- .../IdentitySection/IdentityTokenAuthForm.tsx | 18 +-- .../IdentityUniversalAuthForm.tsx | 18 +-- 25 files changed, 357 insertions(+), 276 deletions(-) diff --git a/backend/src/server/routes/index.ts b/backend/src/server/routes/index.ts index 15221e55b..069d61569 100644 --- a/backend/src/server/routes/index.ts +++ b/backend/src/server/routes/index.ts @@ -816,8 +816,7 @@ export const registerRoutes = async ( }); const identityAccessTokenService = identityAccessTokenServiceFactory({ identityAccessTokenDAL, - identityOrgMembershipDAL, - permissionService + identityOrgMembershipDAL }); const identityProjectService = identityProjectServiceFactory({ permissionService, diff --git a/backend/src/server/routes/v1/identity-access-token-router.ts b/backend/src/server/routes/v1/identity-access-token-router.ts index 8f65a9984..7ed62e679 100644 --- a/backend/src/server/routes/v1/identity-access-token-router.ts +++ b/backend/src/server/routes/v1/identity-access-token-router.ts @@ -2,8 +2,6 @@ import { z } from "zod"; import { UNIVERSAL_AUTH } from "@app/lib/api-docs"; import { writeLimit } from "@app/server/config/rateLimiter"; -import { verifyAuth } from "@app/server/plugins/auth/verify-auth"; -import { AuthMode } from "@app/services/auth/auth-type"; export const registerIdentityAccessTokenRouter = async (server: FastifyZodProvider) => { server.route({ @@ -63,37 +61,4 @@ export const registerIdentityAccessTokenRouter = async (server: FastifyZodProvid }; } }); - - server.route({ - url: "/token/revoke-by-id", - method: "POST", - config: { - rateLimit: writeLimit - }, - onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), - schema: { - description: "Revoke access token by the id of the token", - body: z.object({ - tokenId: z.string().trim() - }), - response: { - 200: z.object({ - message: z.string() - }) - } - }, - handler: async (req) => { - await server.services.identityAccessToken.revokeAccessTokenById({ - actor: req.permission.type, - actorId: req.permission.id, - actorAuthMethod: req.permission.authMethod, - actorOrgId: req.permission.orgId, - ...req.body - }); - - return { - message: "Successfully revoked access token" - }; - } - }); }; diff --git a/backend/src/server/routes/v1/identity-token-auth-router.ts b/backend/src/server/routes/v1/identity-token-auth-router.ts index 6e06c5b6a..ac36c3c58 100644 --- a/backend/src/server/routes/v1/identity-token-auth-router.ts +++ b/backend/src/server/routes/v1/identity-token-auth-router.ts @@ -253,6 +253,15 @@ export const registerIdentityTokenAuthRouter = async (server: FastifyZodProvider } }); + // proposed + // update token by id: PATCH /token-auth/tokens/:tokenId + // revoke token by id: POST /token-auth/tokens/:tokenId/revoke + + // current + // revoke token by id: POST /token/revoke-by-id + + // token-auth/identities/:identityId/tokens + server.route({ method: "POST", url: "/token-auth/identities/:identityId/tokens", @@ -284,7 +293,7 @@ export const registerIdentityTokenAuthRouter = async (server: FastifyZodProvider }, handler: async (req) => { const { identityTokenAuth, accessToken, identityAccessToken, identityMembershipOrg } = - await server.services.identityTokenAuth.createTokenTokenAuth({ + await server.services.identityTokenAuth.createTokenAuthToken({ actor: req.permission.type, actorId: req.permission.id, actorAuthMethod: req.permission.authMethod, @@ -342,7 +351,7 @@ export const registerIdentityTokenAuthRouter = async (server: FastifyZodProvider } }, handler: async (req) => { - const { tokens, identityMembershipOrg } = await server.services.identityTokenAuth.getTokensTokenAuth({ + const { tokens, identityMembershipOrg } = await server.services.identityTokenAuth.getTokenAuthTokens({ actor: req.permission.type, actorId: req.permission.id, actorAuthMethod: req.permission.authMethod, @@ -368,7 +377,7 @@ export const registerIdentityTokenAuthRouter = async (server: FastifyZodProvider server.route({ method: "PATCH", - url: "/token-auth/identities/:identityId/tokens/:tokenId", + url: "/token-auth/tokens/:tokenId", config: { rateLimit: writeLimit }, @@ -381,7 +390,6 @@ export const registerIdentityTokenAuthRouter = async (server: FastifyZodProvider } ], params: z.object({ - identityId: z.string(), tokenId: z.string() }), body: z.object({ @@ -394,12 +402,11 @@ export const registerIdentityTokenAuthRouter = async (server: FastifyZodProvider } }, handler: async (req) => { - const { token, identityMembershipOrg } = await server.services.identityTokenAuth.updateTokenTokenAuth({ + const { token, identityMembershipOrg } = await server.services.identityTokenAuth.updateTokenAuthToken({ actor: req.permission.type, actorId: req.permission.id, actorAuthMethod: req.permission.authMethod, actorOrgId: req.permission.orgId, - identityId: req.params.identityId, tokenId: req.params.tokenId, ...req.body }); @@ -410,7 +417,7 @@ export const registerIdentityTokenAuthRouter = async (server: FastifyZodProvider event: { type: EventType.UPDATE_TOKEN_IDENTITY_TOKEN_AUTH, metadata: { - identityId: req.params.identityId, + identityId: token.identityId, tokenId: token.id, name: req.body.name } @@ -420,4 +427,42 @@ export const registerIdentityTokenAuthRouter = async (server: FastifyZodProvider return { token }; } }); + + server.route({ + method: "POST", + url: "/token-auth/tokens/:tokenId/revoke", + config: { + rateLimit: writeLimit + }, + onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), + schema: { + description: "Revoke token for identity with Token Auth configured", + security: [ + { + bearerAuth: [] + } + ], + params: z.object({ + tokenId: z.string() + }), + response: { + 200: z.object({ + message: z.string() + }) + } + }, + handler: async (req) => { + await server.services.identityTokenAuth.revokeTokenAuthToken({ + actor: req.permission.type, + actorId: req.permission.id, + actorAuthMethod: req.permission.authMethod, + actorOrgId: req.permission.orgId, + tokenId: req.params.tokenId + }); + + return { + message: "Successfully revoked access token" + }; + } + }); }; diff --git a/backend/src/services/identity-access-token/identity-access-token-service.ts b/backend/src/services/identity-access-token/identity-access-token-service.ts index 5998c172c..1da8c06ee 100644 --- a/backend/src/services/identity-access-token/identity-access-token-service.ts +++ b/backend/src/services/identity-access-token/identity-access-token-service.ts @@ -1,9 +1,6 @@ -import { ForbiddenError } from "@casl/ability"; import jwt, { JwtPayload } from "jsonwebtoken"; import { TableName, TIdentityAccessTokens } from "@app/db/schemas"; -import { OrgPermissionActions, OrgPermissionSubjects } from "@app/ee/services/permission/org-permission"; -import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service"; import { getConfig } from "@app/lib/config/env"; import { BadRequestError, UnauthorizedError } from "@app/lib/errors"; import { checkIPAgainstBlocklist, TIp } from "@app/lib/ip"; @@ -11,24 +8,18 @@ import { checkIPAgainstBlocklist, TIp } from "@app/lib/ip"; import { AuthTokenType } from "../auth/auth-type"; import { TIdentityOrgDALFactory } from "../identity/identity-org-dal"; import { TIdentityAccessTokenDALFactory } from "./identity-access-token-dal"; -import { - TIdentityAccessTokenJwtPayload, - TRenewAccessTokenDTO, - TRevokeAccessTokenByIdDTO -} from "./identity-access-token-types"; +import { TIdentityAccessTokenJwtPayload, TRenewAccessTokenDTO } from "./identity-access-token-types"; type TIdentityAccessTokenServiceFactoryDep = { identityAccessTokenDAL: TIdentityAccessTokenDALFactory; identityOrgMembershipDAL: TIdentityOrgDALFactory; - permissionService: Pick; }; export type TIdentityAccessTokenServiceFactory = ReturnType; export const identityAccessTokenServiceFactory = ({ identityAccessTokenDAL, - identityOrgMembershipDAL, - permissionService + identityOrgMembershipDAL }: TIdentityAccessTokenServiceFactoryDep) => { const validateAccessTokenExp = async (identityAccessToken: TIdentityAccessTokens) => { const { @@ -147,43 +138,6 @@ export const identityAccessTokenServiceFactory = ({ return { revokedToken }; }; - const revokeAccessTokenById = async ({ - tokenId, - actorId, - actor, - actorAuthMethod, - actorOrgId - }: TRevokeAccessTokenByIdDTO) => { - const identityAccessToken = await identityAccessTokenDAL.findOne({ - [`${TableName.IdentityAccessToken}.id` as "id"]: tokenId, - isAccessTokenRevoked: false - }); - if (!identityAccessToken) throw new UnauthorizedError(); - - const identityOrgMembership = await identityOrgMembershipDAL.findOne({ - identityId: identityAccessToken.identityId - }); - - if (!identityOrgMembership) { - throw new UnauthorizedError({ message: "Identity does not belong to any organization" }); - } - - const { permission } = await permissionService.getOrgPermission( - actor, - actorId, - identityOrgMembership.orgId, - actorAuthMethod, - actorOrgId - ); - ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.Identity); - - const revokedToken = await identityAccessTokenDAL.updateById(identityAccessToken.id, { - isAccessTokenRevoked: true - }); - - return { revokedToken }; - }; - const fnValidateIdentityAccessToken = async (token: TIdentityAccessTokenJwtPayload, ipAddress?: string) => { const identityAccessToken = await identityAccessTokenDAL.findOne({ [`${TableName.IdentityAccessToken}.id` as "id"]: token.identityAccessTokenId, @@ -221,5 +175,5 @@ export const identityAccessTokenServiceFactory = ({ return { ...identityAccessToken, orgId: identityOrgMembership.orgId }; }; - return { renewAccessToken, revokeAccessToken, revokeAccessTokenById, fnValidateIdentityAccessToken }; + return { renewAccessToken, revokeAccessToken, fnValidateIdentityAccessToken }; }; diff --git a/backend/src/services/identity-access-token/identity-access-token-types.ts b/backend/src/services/identity-access-token/identity-access-token-types.ts index 5c67454ad..86967df76 100644 --- a/backend/src/services/identity-access-token/identity-access-token-types.ts +++ b/backend/src/services/identity-access-token/identity-access-token-types.ts @@ -1,5 +1,3 @@ -import { TProjectPermission } from "@app/lib/types"; - export type TRenewAccessTokenDTO = { accessToken: string; }; @@ -10,7 +8,3 @@ export type TIdentityAccessTokenJwtPayload = { identityAccessTokenId: string; authTokenType: string; }; - -export type TRevokeAccessTokenByIdDTO = { - tokenId: string; -} & Omit; 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 c33147238..198b76266 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 @@ -1,13 +1,13 @@ import { ForbiddenError } from "@casl/ability"; import jwt from "jsonwebtoken"; -import { IdentityAuthMethod } from "@app/db/schemas"; +import { IdentityAuthMethod, TableName } from "@app/db/schemas"; import { TLicenseServiceFactory } from "@app/ee/services/license/license-service"; import { OrgPermissionActions, OrgPermissionSubjects } from "@app/ee/services/permission/org-permission"; import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service"; import { isAtLeastAsPrivileged } from "@app/lib/casl"; import { getConfig } from "@app/lib/config/env"; -import { BadRequestError, ForbiddenRequestError } from "@app/lib/errors"; +import { BadRequestError, ForbiddenRequestError, NotFoundError, UnauthorizedError } from "@app/lib/errors"; import { extractIPDetails, isValidIpOrCidr } from "@app/lib/ip"; import { ActorType, AuthTokenType } from "../auth/auth-type"; @@ -18,12 +18,13 @@ import { TIdentityAccessTokenJwtPayload } from "../identity-access-token/identit import { TIdentityTokenAuthDALFactory } from "./identity-token-auth-dal"; import { TAttachTokenAuthDTO, - TCreateTokenTokenAuthDTO, + TCreateTokenAuthTokenDTO, TGetTokenAuthDTO, - TGetTokensTokenAuthDTO, + TGetTokenAuthTokensDTO, TRevokeTokenAuthDTO, + TRevokeTokenAuthTokenDTO, TUpdateTokenAuthDTO, - TUpdateTokenTokenAuthDTO + TUpdateTokenAuthTokenDTO } from "./identity-token-auth-types"; type TIdentityTokenAuthServiceFactoryDep = { @@ -33,7 +34,10 @@ type TIdentityTokenAuthServiceFactoryDep = { >; identityDAL: Pick; identityOrgMembershipDAL: Pick; - identityAccessTokenDAL: Pick; + identityAccessTokenDAL: Pick< + TIdentityAccessTokenDALFactory, + "create" | "find" | "update" | "findById" | "findOne" | "updateById" + >; permissionService: Pick; licenseService: Pick; }; @@ -243,7 +247,7 @@ export const identityTokenAuthServiceFactory = ({ ); const hasPriviledge = isAtLeastAsPrivileged(permission, rolePermission); if (!hasPriviledge) - throw new ForbiddenRequestError({ + throw new UnauthorizedError({ message: "Failed to revoke Token Auth of identity with more privileged role" }); @@ -255,14 +259,14 @@ export const identityTokenAuthServiceFactory = ({ return revokedIdentityTokenAuth; }; - const createTokenTokenAuth = async ({ + const createTokenAuthToken = async ({ identityId, actorId, actor, actorAuthMethod, actorOrgId, name - }: TCreateTokenTokenAuthDTO) => { + }: TCreateTokenAuthTokenDTO) => { const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId }); if (!identityMembershipOrg) throw new BadRequestError({ message: "Failed to find identity" }); if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.TOKEN_AUTH) @@ -328,7 +332,7 @@ export const identityTokenAuthServiceFactory = ({ return { accessToken, identityTokenAuth, identityAccessToken, identityMembershipOrg }; }; - const getTokensTokenAuth = async ({ + const getTokenAuthTokens = async ({ identityId, offset = 0, limit = 20, @@ -336,7 +340,7 @@ export const identityTokenAuthServiceFactory = ({ actor, actorAuthMethod, actorOrgId - }: TGetTokensTokenAuthDTO) => { + }: TGetTokenAuthTokensDTO) => { const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId }); if (!identityMembershipOrg) throw new BadRequestError({ message: "Failed to find identity" }); if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.TOKEN_AUTH) @@ -350,20 +354,7 @@ export const identityTokenAuthServiceFactory = ({ actorAuthMethod, actorOrgId ); - ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.Identity); - - const { permission: rolePermission } = await permissionService.getOrgPermission( - ActorType.IDENTITY, - identityMembershipOrg.identityId, - identityMembershipOrg.orgId, - actorAuthMethod, - actorOrgId - ); - const hasPriviledge = isAtLeastAsPrivileged(permission, rolePermission); - if (!hasPriviledge) - throw new ForbiddenRequestError({ - message: "Failed to get tokens for identity with more privileged role" - }); + ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Identity); const tokens = await identityAccessTokenDAL.find( { @@ -375,16 +366,17 @@ export const identityTokenAuthServiceFactory = ({ return { tokens, identityMembershipOrg }; }; - const updateTokenTokenAuth = async ({ - identityId, + const updateTokenAuthToken = async ({ tokenId, name, actorId, actor, actorAuthMethod, actorOrgId - }: TUpdateTokenTokenAuthDTO) => { - const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId }); + }: TUpdateTokenAuthTokenDTO) => { + const foundToken = await identityAccessTokenDAL.findById(tokenId); + if (!foundToken) throw new NotFoundError({ message: "Failed to find token" }); + const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId: foundToken.identityId }); if (!identityMembershipOrg) throw new BadRequestError({ message: "Failed to find identity" }); if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.TOKEN_AUTH) throw new BadRequestError({ @@ -414,7 +406,7 @@ export const identityTokenAuthServiceFactory = ({ const [token] = await identityAccessTokenDAL.update( { - identityId, + identityId: foundToken.identityId, id: tokenId }, { @@ -425,13 +417,54 @@ export const identityTokenAuthServiceFactory = ({ return { token, identityMembershipOrg }; }; + const revokeTokenAuthToken = async ({ + tokenId, + actorId, + actor, + actorAuthMethod, + actorOrgId + }: TRevokeTokenAuthTokenDTO) => { + const identityAccessToken = await identityAccessTokenDAL.findOne({ + [`${TableName.IdentityAccessToken}.id` as "id"]: tokenId, + isAccessTokenRevoked: false + }); + if (!identityAccessToken) + throw new NotFoundError({ + message: "Failed to find token" + }); + + const identityOrgMembership = await identityOrgMembershipDAL.findOne({ + identityId: identityAccessToken.identityId + }); + + if (!identityOrgMembership) { + throw new UnauthorizedError({ message: "Identity does not belong to any organization" }); + } + + const { permission } = await permissionService.getOrgPermission( + actor, + actorId, + identityOrgMembership.orgId, + actorAuthMethod, + actorOrgId + ); + ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.Identity); + + const revokedToken = await identityAccessTokenDAL.updateById(identityAccessToken.id, { + isAccessTokenRevoked: true + }); + + return { revokedToken }; + }; + return { attachTokenAuth, updateTokenAuth, getTokenAuth, revokeIdentityTokenAuth, - createTokenTokenAuth, - getTokensTokenAuth, - updateTokenTokenAuth + createTokenAuthToken, + getTokenAuthTokens, + updateTokenAuthToken, + revokeTokenAuthToken }; }; diff --git a/backend/src/services/identity-token-auth/identity-token-auth-types.ts b/backend/src/services/identity-token-auth/identity-token-auth-types.ts index 4419abc36..12c689728 100644 --- a/backend/src/services/identity-token-auth/identity-token-auth-types.ts +++ b/backend/src/services/identity-token-auth/identity-token-auth-types.ts @@ -24,19 +24,22 @@ export type TRevokeTokenAuthDTO = { identityId: string; } & Omit; -export type TCreateTokenTokenAuthDTO = { +export type TCreateTokenAuthTokenDTO = { identityId: string; name?: string; } & Omit; -export type TGetTokensTokenAuthDTO = { +export type TGetTokenAuthTokensDTO = { identityId: string; offset: number; limit: number; } & Omit; -export type TUpdateTokenTokenAuthDTO = { - identityId: string; +export type TUpdateTokenAuthTokenDTO = { tokenId: string; name?: string; } & Omit; + +export type TRevokeTokenAuthTokenDTO = { + tokenId: string; +} & Omit; diff --git a/backend/src/services/identity/identity-service.ts b/backend/src/services/identity/identity-service.ts index d3fc9c788..78dcdda4e 100644 --- a/backend/src/services/identity/identity-service.ts +++ b/backend/src/services/identity/identity-service.ts @@ -5,7 +5,7 @@ import { TLicenseServiceFactory } from "@app/ee/services/license/license-service import { OrgPermissionActions, OrgPermissionSubjects } from "@app/ee/services/permission/org-permission"; import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service"; import { isAtLeastAsPrivileged } from "@app/lib/casl"; -import { BadRequestError, ForbiddenRequestError } from "@app/lib/errors"; +import { BadRequestError, ForbiddenRequestError, NotFoundError } from "@app/lib/errors"; import { TOrgPermission } from "@app/lib/types"; import { TIdentityProjectDALFactory } from "@app/services/identity-project/identity-project-dal"; @@ -213,7 +213,7 @@ export const identityServiceFactory = ({ actorOrgId }: TListProjectIdentitiesByIdentityIdDTO) => { const identityOrgMembership = await identityOrgMembershipDAL.findOne({ identityId }); - if (!identityOrgMembership) throw new BadRequestError({ message: `Failed to find identity with id ${identityId}` }); + if (!identityOrgMembership) throw new NotFoundError({ message: `Failed to find identity with id ${identityId}` }); const { permission } = await permissionService.getOrgPermission( actor, diff --git a/frontend/src/hooks/api/identities/index.tsx b/frontend/src/hooks/api/identities/index.tsx index b4d4f9e6d..ceece2c13 100644 --- a/frontend/src/hooks/api/identities/index.tsx +++ b/frontend/src/hooks/api/identities/index.tsx @@ -17,16 +17,16 @@ export { useDeleteIdentityKubernetesAuth, useDeleteIdentityTokenAuth, useDeleteIdentityUniversalAuth, + useRevokeIdentityTokenAuthToken, useRevokeIdentityUniversalAuthClientSecret, - useRevokeToken, useUpdateIdentity, useUpdateIdentityAwsAuth, useUpdateIdentityAzureAuth, useUpdateIdentityGcpAuth, useUpdateIdentityKubernetesAuth, useUpdateIdentityTokenAuth, - useUpdateIdentityUniversalAuth, - useUpdateTokenIdentityTokenAuth} from "./mutations"; + useUpdateIdentityTokenAuthToken, + useUpdateIdentityUniversalAuth} from "./mutations"; export { useGetIdentityAwsAuth, useGetIdentityAzureAuth, @@ -37,4 +37,5 @@ export { useGetIdentityTokenAuth, useGetIdentityTokensTokenAuth, useGetIdentityUniversalAuth, - useGetIdentityUniversalAuthClientSecrets} from "./queries"; + useGetIdentityUniversalAuthClientSecrets +} from "./queries"; diff --git a/frontend/src/hooks/api/identities/mutations.tsx b/frontend/src/hooks/api/identities/mutations.tsx index 323b45fd5..86fca63e9 100644 --- a/frontend/src/hooks/api/identities/mutations.tsx +++ b/frontend/src/hooks/api/identities/mutations.tsx @@ -42,7 +42,8 @@ import { UpdateIdentityKubernetesAuthDTO, UpdateIdentityTokenAuthDTO, UpdateIdentityUniversalAuthDTO, - UpdateTokenIdentityTokenAuthDTO} from "./types"; + UpdateTokenIdentityTokenAuthDTO +} from "./types"; export const useCreateIdentity = () => { const queryClient = useQueryClient(); @@ -706,14 +707,14 @@ export const useCreateTokenIdentityTokenAuth = () => { }); }; -export const useUpdateTokenIdentityTokenAuth = () => { +export const useUpdateIdentityTokenAuthToken = () => { const queryClient = useQueryClient(); return useMutation({ - mutationFn: async ({ identityId, tokenId, name }) => { + mutationFn: async ({ tokenId, name }) => { const { data: { token } } = await apiRequest.patch<{ token: IdentityAccessToken }>( - `/api/v1/auth/token-auth/identities/${identityId}/tokens/${tokenId}`, + `/api/v1/auth/token-auth/tokens/${tokenId}`, { name } @@ -727,13 +728,13 @@ export const useUpdateTokenIdentityTokenAuth = () => { }); }; -export const useRevokeToken = () => { +export const useRevokeIdentityTokenAuthToken = () => { const queryClient = useQueryClient(); return useMutation({ mutationFn: async ({ tokenId }) => { - const { data } = await apiRequest.post("/api/v1/auth/token/revoke-by-id", { - tokenId - }); + const { data } = await apiRequest.post( + `/api/v1/auth/token-auth/tokens/${tokenId}/revoke` + ); return data; }, diff --git a/frontend/src/views/Org/IdentityPage/IdentityPage.tsx b/frontend/src/views/Org/IdentityPage/IdentityPage.tsx index 548ea2266..1be789baa 100644 --- a/frontend/src/views/Org/IdentityPage/IdentityPage.tsx +++ b/frontend/src/views/Org/IdentityPage/IdentityPage.tsx @@ -21,9 +21,8 @@ import { withPermission } from "@app/hoc"; import { useDeleteIdentity, useGetIdentityById, - useRevokeIdentityUniversalAuthClientSecret, - useRevokeToken -} from "@app/hooks/api"; + useRevokeIdentityTokenAuthToken, + useRevokeIdentityUniversalAuthClientSecret} from "@app/hooks/api"; import { usePopUp } from "@app/hooks/usePopUp"; import { IdentityAuthMethodModal } from "../MembersPage/components/OrgIdentityTab/components/IdentitySection/IdentityAuthMethodModal"; @@ -35,7 +34,8 @@ import { IdentityDetailsSection, IdentityProjectsSection, IdentityTokenListModal, - IdentityTokenModal} from "./components"; + IdentityTokenModal +} from "./components"; export const IdentityPage = withPermission( () => { @@ -45,13 +45,14 @@ export const IdentityPage = withPermission( const orgId = currentOrg?.id || ""; const { data } = useGetIdentityById(identityId); const { mutateAsync: deleteIdentity } = useDeleteIdentity(); - const { mutateAsync: revokeToken } = useRevokeToken(); + const { mutateAsync: revokeToken } = useRevokeIdentityTokenAuthToken(); const { mutateAsync: revokeClientSecret } = useRevokeIdentityUniversalAuthClientSecret(); const { popUp, handlePopUpOpen, handlePopUpClose, handlePopUpToggle } = usePopUp([ "identity", "deleteIdentity", "identityAuthMethod", + "revokeAuthMethod", "token", "tokenList", "revokeToken", diff --git a/frontend/src/views/Org/IdentityPage/components/IdentityAuthenticationSection/IdentityAuthenticationSection.tsx b/frontend/src/views/Org/IdentityPage/components/IdentityAuthenticationSection/IdentityAuthenticationSection.tsx index 7aad5c558..be7c744ce 100644 --- a/frontend/src/views/Org/IdentityPage/components/IdentityAuthenticationSection/IdentityAuthenticationSection.tsx +++ b/frontend/src/views/Org/IdentityPage/components/IdentityAuthenticationSection/IdentityAuthenticationSection.tsx @@ -66,18 +66,6 @@ export const IdentityAuthenticationSection = ({ identityId, handlePopUpOpen }: P

Auth Method

- {/* */}

{data.identity.authMethod diff --git a/frontend/src/views/Org/IdentityPage/components/IdentityAuthenticationSection/IdentityClientSecrets.tsx b/frontend/src/views/Org/IdentityPage/components/IdentityAuthenticationSection/IdentityClientSecrets.tsx index 781bb915c..21402fb6d 100644 --- a/frontend/src/views/Org/IdentityPage/components/IdentityAuthenticationSection/IdentityClientSecrets.tsx +++ b/frontend/src/views/Org/IdentityPage/components/IdentityAuthenticationSection/IdentityClientSecrets.tsx @@ -1,10 +1,11 @@ -import { faKey, faTrash } from "@fortawesome/free-solid-svg-icons"; +import { faCheck, faCopy,faKey, faTrash } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { format } from "date-fns"; import { OrgPermissionCan } from "@app/components/permissions"; import { Button, IconButton, Tooltip } from "@app/components/v2"; import { OrgPermissionActions, OrgPermissionSubjects } from "@app/context"; +import { useTimedReset } from "@app/hooks"; import { useGetIdentityById, useGetIdentityUniversalAuth, @@ -25,6 +26,10 @@ type Props = { const SHOW_LIMIT = 3; export const IdentityClientSecrets = ({ identityId, handlePopUpOpen }: Props) => { + const [copyTextClientId, isCopyingClientId, setCopyTextClientId] = useTimedReset({ + initialState: "Copy Client ID to clipboard" + }); + const { data } = useGetIdentityById(identityId); const { data: identityUniversalAuth } = useGetIdentityUniversalAuth(identityId); const { data: clientSecrets } = useGetIdentityUniversalAuthClientSecrets(identityId); @@ -32,7 +37,22 @@ export const IdentityClientSecrets = ({ identityId, handlePopUpOpen }: Props) =>

Client ID

-

{identityUniversalAuth?.clientId ?? ""}

+
+

{identityUniversalAuth?.clientId ?? ""}

+ + { + navigator.clipboard.writeText(identityUniversalAuth?.clientId ?? ""); + setCopyTextClientId("Copied"); + }} + > + + + +
{clientSecrets?.length ? (
diff --git a/frontend/src/views/Org/IdentityPage/components/IdentityAuthenticationSection/IdentityTokens.tsx b/frontend/src/views/Org/IdentityPage/components/IdentityAuthenticationSection/IdentityTokens.tsx index e97b2faec..64a4c96b2 100644 --- a/frontend/src/views/Org/IdentityPage/components/IdentityAuthenticationSection/IdentityTokens.tsx +++ b/frontend/src/views/Org/IdentityPage/components/IdentityAuthenticationSection/IdentityTokens.tsx @@ -86,17 +86,19 @@ export const IdentityTokens = ({ identityId, handlePopUpOpen }: Props) => { > Edit Token - { - handlePopUpOpen("revokeToken", { - identityId, - tokenId: token.id, - name: token.name - }); - }} - > - Revoke Token - + {!token.isAccessTokenRevoked && ( + { + handlePopUpOpen("revokeToken", { + identityId, + tokenId: token.id, + name: token.name + }); + }} + > + Revoke Token + + )}
diff --git a/frontend/src/views/Org/IdentityPage/components/IdentityDetailsSection.tsx b/frontend/src/views/Org/IdentityPage/components/IdentityDetailsSection.tsx index 6a6843d85..c6d7f0ce1 100644 --- a/frontend/src/views/Org/IdentityPage/components/IdentityDetailsSection.tsx +++ b/frontend/src/views/Org/IdentityPage/components/IdentityDetailsSection.tsx @@ -1,9 +1,10 @@ -import { faPencil } from "@fortawesome/free-solid-svg-icons"; +import { faCheck,faCopy, faPencil } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { OrgPermissionCan } from "@app/components/permissions"; -import { IconButton,Tooltip } from "@app/components/v2"; +import { IconButton, Tooltip } from "@app/components/v2"; import { OrgPermissionActions, OrgPermissionSubjects } from "@app/context"; +import { useTimedReset } from "@app/hooks"; import { useGetIdentityById } from "@app/hooks/api"; import { UsePopUpState } from "@app/hooks/usePopUp"; @@ -16,6 +17,10 @@ type Props = { }; export const IdentityDetailsSection = ({ identityId, handlePopUpOpen }: Props) => { + const [copyTextId, isCopyingId, setCopyTextId] = useTimedReset({ + initialState: "Copy ID to clipboard" + }); + const { data } = useGetIdentityById(identityId); return data ? (
@@ -49,7 +54,22 @@ export const IdentityDetailsSection = ({ identityId, handlePopUpOpen }: Props) =

ID

-

{data.identity.id}

+
+

{data.identity.id}

+ + { + navigator.clipboard.writeText(data.identity.id); + setCopyTextId("Copied"); + }} + > + + + +

Name

diff --git a/frontend/src/views/Org/IdentityPage/components/IdentityTokenModal.tsx b/frontend/src/views/Org/IdentityPage/components/IdentityTokenModal.tsx index 24a2a6baf..dfc26592e 100644 --- a/frontend/src/views/Org/IdentityPage/components/IdentityTokenModal.tsx +++ b/frontend/src/views/Org/IdentityPage/components/IdentityTokenModal.tsx @@ -16,7 +16,7 @@ import { Tooltip } from "@app/components/v2"; import { useTimedReset } from "@app/hooks"; -import { useCreateTokenIdentityTokenAuth, useUpdateTokenIdentityTokenAuth } from "@app/hooks/api"; +import { useCreateTokenIdentityTokenAuth, useUpdateIdentityTokenAuthToken } from "@app/hooks/api"; import { UsePopUpState } from "@app/hooks/usePopUp"; const schema = z @@ -34,7 +34,7 @@ type Props = { export const IdentityTokenModal = ({ popUp, handlePopUpToggle }: Props) => { const { mutateAsync: createToken } = useCreateTokenIdentityTokenAuth(); - const { mutateAsync: updateToken } = useUpdateTokenIdentityTokenAuth(); + const { mutateAsync: updateToken } = useUpdateIdentityTokenAuthToken(); const [token, setToken] = useState(""); const [copyTextToken, isCopyingToken, setCopyTextToken] = useTimedReset({ initialState: "Copy to clipboard" diff --git a/frontend/src/views/Org/MembersPage/components/OrgIdentityTab/components/IdentitySection/IdentityAuthMethodModal.tsx b/frontend/src/views/Org/MembersPage/components/OrgIdentityTab/components/IdentitySection/IdentityAuthMethodModal.tsx index bee7b65a6..5acdd6e3b 100644 --- a/frontend/src/views/Org/MembersPage/components/OrgIdentityTab/components/IdentitySection/IdentityAuthMethodModal.tsx +++ b/frontend/src/views/Org/MembersPage/components/OrgIdentityTab/components/IdentitySection/IdentityAuthMethodModal.tsx @@ -3,15 +3,24 @@ import { Controller, useForm } from "react-hook-form"; import { yupResolver } from "@hookform/resolvers/yup"; import * as yup from "yup"; +import { createNotification } from "@app/components/notifications"; import { + DeleteActionModal, FormControl, Modal, ModalContent, Select, SelectItem, - UpgradePlanModal -} from "@app/components/v2"; -import { IdentityAuthMethod } from "@app/hooks/api/identities"; + UpgradePlanModal} from "@app/components/v2"; +import { useOrganization } from "@app/context"; +import { + useDeleteIdentityAwsAuth, + useDeleteIdentityAzureAuth, + useDeleteIdentityGcpAuth, + useDeleteIdentityKubernetesAuth, + useDeleteIdentityTokenAuth, + useDeleteIdentityUniversalAuth} from "@app/hooks/api"; +import { IdentityAuthMethod , identityAuthToNameMap } from "@app/hooks/api/identities"; import { UsePopUpState } from "@app/hooks/usePopUp"; import { IdentityAwsAuthForm } from "./IdentityAwsAuthForm"; @@ -22,10 +31,10 @@ import { IdentityTokenAuthForm } from "./IdentityTokenAuthForm"; import { IdentityUniversalAuthForm } from "./IdentityUniversalAuthForm"; type Props = { - popUp: UsePopUpState<["identityAuthMethod", "upgradePlan"]>; + popUp: UsePopUpState<["identityAuthMethod", "upgradePlan", "revokeAuthMethod"]>; handlePopUpOpen: (popUpName: keyof UsePopUpState<["upgradePlan"]>) => void; handlePopUpToggle: ( - popUpName: keyof UsePopUpState<["identityAuthMethod", "upgradePlan"]>, + popUpName: keyof UsePopUpState<["identityAuthMethod", "upgradePlan", "revokeAuthMethod"]>, state?: boolean ) => void; }; @@ -48,6 +57,16 @@ const schema = yup export type FormData = yup.InferType; export const IdentityAuthMethodModal = ({ popUp, handlePopUpOpen, handlePopUpToggle }: Props) => { + const { currentOrg } = useOrganization(); + const orgId = currentOrg?.id || ""; + + const { mutateAsync: revokeUniversalAuth } = useDeleteIdentityUniversalAuth(); + const { mutateAsync: revokeTokenAuth } = useDeleteIdentityTokenAuth(); + const { mutateAsync: revokeKubernetesAuth } = useDeleteIdentityKubernetesAuth(); + const { mutateAsync: revokeGcpAuth } = useDeleteIdentityGcpAuth(); + const { mutateAsync: revokeAwsAuth } = useDeleteIdentityAwsAuth(); + const { mutateAsync: revokeAzureAuth } = useDeleteIdentityAzureAuth(); + const { control, watch, setValue } = useForm({ resolver: yupResolver(schema), defaultValues: { @@ -128,13 +147,84 @@ export const IdentityAuthMethodModal = ({ popUp, handlePopUpOpen, handlePopUpTog /> ); } - default: { return
; } } }; + const onRevokeAuthMethodSubmit = async () => { + if (!identityAuthMethodData.authMethod) return; + if (!orgId) return; + try { + console.log("onRevokeAuthMethodSubmit identityId: ", identityAuthMethodData); + switch (identityAuthMethodData.authMethod) { + case IdentityAuthMethod.UNIVERSAL_AUTH: { + await revokeUniversalAuth({ + identityId: identityAuthMethodData.identityId, + organizationId: orgId + }); + break; + } + case IdentityAuthMethod.TOKEN_AUTH: { + await revokeTokenAuth({ + identityId: identityAuthMethodData.identityId, + organizationId: orgId + }); + break; + } + case IdentityAuthMethod.KUBERNETES_AUTH: { + await revokeKubernetesAuth({ + identityId: identityAuthMethodData.identityId, + organizationId: orgId + }); + break; + } + case IdentityAuthMethod.GCP_AUTH: { + await revokeGcpAuth({ + identityId: identityAuthMethodData.identityId, + organizationId: orgId + }); + break; + } + case IdentityAuthMethod.AWS_AUTH: { + await revokeAwsAuth({ + identityId: identityAuthMethodData.identityId, + organizationId: orgId + }); + break; + } + case IdentityAuthMethod.AZURE_AUTH: { + await revokeAzureAuth({ + identityId: identityAuthMethodData.identityId, + organizationId: orgId + }); + break; + } + default: + break; + } + + createNotification({ + text: `Successfully removed ${ + identityAuthToNameMap[identityAuthMethodData.authMethod] + } on ${identityAuthMethodData.name}`, + type: "success" + }); + + handlePopUpToggle("revokeAuthMethod", false); + handlePopUpToggle("identityAuthMethod", false); + } catch (err) { + console.error(err); + createNotification({ + text: `Failed to remove ${identityAuthToNameMap[identityAuthMethodData.authMethod]} on ${ + identityAuthMethodData.name + }`, + type: "error" + }); + } + }; + return ( handlePopUpToggle("upgradePlan", isOpen)} text="You can use IP allowlisting if you switch to Infisical's Pro plan." /> + handlePopUpToggle("revokeAuthMethod", isOpen)} + deleteKey="confirm" + onDeleteApproved={onRevokeAuthMethodSubmit} + /> ); diff --git a/frontend/src/views/Org/MembersPage/components/OrgIdentityTab/components/IdentitySection/IdentityAwsAuthForm.tsx b/frontend/src/views/Org/MembersPage/components/OrgIdentityTab/components/IdentitySection/IdentityAwsAuthForm.tsx index 3fbd15026..9c81f308a 100644 --- a/frontend/src/views/Org/MembersPage/components/OrgIdentityTab/components/IdentitySection/IdentityAwsAuthForm.tsx +++ b/frontend/src/views/Org/MembersPage/components/OrgIdentityTab/components/IdentitySection/IdentityAwsAuthForm.tsx @@ -10,9 +10,9 @@ import { Button, FormControl, IconButton, Input } from "@app/components/v2"; import { useOrganization, useSubscription } from "@app/context"; import { useAddIdentityAwsAuth, - useDeleteIdentityAwsAuth, useGetIdentityAwsAuth, - useUpdateIdentityAwsAuth} from "@app/hooks/api"; + useUpdateIdentityAwsAuth +} from "@app/hooks/api"; import { IdentityAuthMethod } from "@app/hooks/api/identities"; import { IdentityTrustedIp } from "@app/hooks/api/identities/types"; import { UsePopUpState } from "@app/hooks/usePopUp"; @@ -42,7 +42,7 @@ export type FormData = yup.InferType; type Props = { handlePopUpOpen: (popUpName: keyof UsePopUpState<["upgradePlan"]>) => void; handlePopUpToggle: ( - popUpName: keyof UsePopUpState<["identityAuthMethod"]>, + popUpName: keyof UsePopUpState<["identityAuthMethod", "revokeAuthMethod"]>, state?: boolean ) => void; identityAuthMethodData: { @@ -63,7 +63,6 @@ export const IdentityAwsAuthForm = ({ const { mutateAsync: addMutateAsync } = useAddIdentityAwsAuth(); const { mutateAsync: updateMutateAsync } = useUpdateIdentityAwsAuth(); - const { mutateAsync: deleteMutateAsync } = useDeleteIdentityAwsAuth(); const { data } = useGetIdentityAwsAuth(identityAuthMethodData?.identityId ?? ""); @@ -346,7 +345,7 @@ export const IdentityAwsAuthForm = ({ variant="plain" onClick={() => handlePopUpToggle("identityAuthMethod", false)} > - {identityAuthMethodData?.authMethod ? "Cancel" : "Skip"} + Cancel
{identityAuthMethodData?.authMethod && ( @@ -355,14 +354,7 @@ export const IdentityAwsAuthForm = ({ colorSchema="danger" isLoading={isSubmitting} isDisabled={isSubmitting} - onClick={async () => { - await deleteMutateAsync({ - identityId: identityAuthMethodData.identityId, - organizationId: orgId - }); - - handlePopUpToggle("identityAuthMethod", false); - }} + onClick={() => handlePopUpToggle("revokeAuthMethod", true)} > Remove Auth Method diff --git a/frontend/src/views/Org/MembersPage/components/OrgIdentityTab/components/IdentitySection/IdentityAzureAuthForm.tsx b/frontend/src/views/Org/MembersPage/components/OrgIdentityTab/components/IdentitySection/IdentityAzureAuthForm.tsx index ff6570d6c..c0aaca2f6 100644 --- a/frontend/src/views/Org/MembersPage/components/OrgIdentityTab/components/IdentitySection/IdentityAzureAuthForm.tsx +++ b/frontend/src/views/Org/MembersPage/components/OrgIdentityTab/components/IdentitySection/IdentityAzureAuthForm.tsx @@ -10,9 +10,9 @@ import { Button, FormControl, IconButton, Input } from "@app/components/v2"; import { useOrganization, useSubscription } from "@app/context"; import { useAddIdentityAzureAuth, - useDeleteIdentityAzureAuth, useGetIdentityAzureAuth, - useUpdateIdentityAzureAuth} from "@app/hooks/api"; + useUpdateIdentityAzureAuth +} from "@app/hooks/api"; import { IdentityAuthMethod } from "@app/hooks/api/identities"; import { IdentityTrustedIp } from "@app/hooks/api/identities/types"; import { UsePopUpState } from "@app/hooks/usePopUp"; @@ -40,7 +40,7 @@ export type FormData = z.infer; type Props = { handlePopUpOpen: (popUpName: keyof UsePopUpState<["upgradePlan"]>) => void; handlePopUpToggle: ( - popUpName: keyof UsePopUpState<["identityAuthMethod"]>, + popUpName: keyof UsePopUpState<["identityAuthMethod", "revokeAuthMethod"]>, state?: boolean ) => void; identityAuthMethodData: { @@ -61,7 +61,6 @@ export const IdentityAzureAuthForm = ({ const { mutateAsync: addMutateAsync } = useAddIdentityAzureAuth(); const { mutateAsync: updateMutateAsync } = useUpdateIdentityAzureAuth(); - const { mutateAsync: deleteMutateAsync } = useDeleteIdentityAzureAuth(); const { data } = useGetIdentityAzureAuth(identityAuthMethodData?.identityId ?? ""); @@ -344,7 +343,7 @@ export const IdentityAzureAuthForm = ({ variant="plain" onClick={() => handlePopUpToggle("identityAuthMethod", false)} > - {identityAuthMethodData?.authMethod ? "Cancel" : "Skip"} + Cancel
{identityAuthMethodData?.authMethod && ( @@ -353,14 +352,7 @@ export const IdentityAzureAuthForm = ({ colorSchema="danger" isLoading={isSubmitting} isDisabled={isSubmitting} - onClick={async () => { - await deleteMutateAsync({ - identityId: identityAuthMethodData.identityId, - organizationId: orgId - }); - - handlePopUpToggle("identityAuthMethod", false); - }} + onClick={() => handlePopUpToggle("revokeAuthMethod", true)} > Remove Auth Method diff --git a/frontend/src/views/Org/MembersPage/components/OrgIdentityTab/components/IdentitySection/IdentityGcpAuthForm.tsx b/frontend/src/views/Org/MembersPage/components/OrgIdentityTab/components/IdentitySection/IdentityGcpAuthForm.tsx index 2a5a10d61..eb07c3c36 100644 --- a/frontend/src/views/Org/MembersPage/components/OrgIdentityTab/components/IdentitySection/IdentityGcpAuthForm.tsx +++ b/frontend/src/views/Org/MembersPage/components/OrgIdentityTab/components/IdentitySection/IdentityGcpAuthForm.tsx @@ -10,9 +10,9 @@ import { Button, FormControl, IconButton, Input, Select, SelectItem } from "@app import { useOrganization, useSubscription } from "@app/context"; import { useAddIdentityGcpAuth, - useDeleteIdentityGcpAuth, useGetIdentityGcpAuth, - useUpdateIdentityGcpAuth} from "@app/hooks/api"; + useUpdateIdentityGcpAuth +} from "@app/hooks/api"; import { IdentityAuthMethod } from "@app/hooks/api/identities"; import { IdentityTrustedIp } from "@app/hooks/api/identities/types"; import { UsePopUpState } from "@app/hooks/usePopUp"; @@ -41,7 +41,7 @@ export type FormData = z.infer; type Props = { handlePopUpOpen: (popUpName: keyof UsePopUpState<["upgradePlan"]>) => void; handlePopUpToggle: ( - popUpName: keyof UsePopUpState<["identityAuthMethod"]>, + popUpName: keyof UsePopUpState<["identityAuthMethod", "revokeAuthMethod"]>, state?: boolean ) => void; identityAuthMethodData: { @@ -62,7 +62,6 @@ export const IdentityGcpAuthForm = ({ const { mutateAsync: addMutateAsync } = useAddIdentityGcpAuth(); const { mutateAsync: updateMutateAsync } = useUpdateIdentityGcpAuth(); - const { mutateAsync: deleteMutateAsync } = useDeleteIdentityGcpAuth(); const { data } = useGetIdentityGcpAuth(identityAuthMethodData?.identityId ?? ""); @@ -378,7 +377,7 @@ export const IdentityGcpAuthForm = ({ variant="plain" onClick={() => handlePopUpToggle("identityAuthMethod", false)} > - {identityAuthMethodData?.authMethod ? "Cancel" : "Skip"} + Cancel
{identityAuthMethodData?.authMethod && ( @@ -387,14 +386,7 @@ export const IdentityGcpAuthForm = ({ colorSchema="danger" isLoading={isSubmitting} isDisabled={isSubmitting} - onClick={async () => { - await deleteMutateAsync({ - identityId: identityAuthMethodData.identityId, - organizationId: orgId - }); - - handlePopUpToggle("identityAuthMethod", false); - }} + onClick={() => handlePopUpToggle("revokeAuthMethod", true)} > Remove Auth Method diff --git a/frontend/src/views/Org/MembersPage/components/OrgIdentityTab/components/IdentitySection/IdentityKubernetesAuthForm.tsx b/frontend/src/views/Org/MembersPage/components/OrgIdentityTab/components/IdentitySection/IdentityKubernetesAuthForm.tsx index f212aebbf..6baa6a405 100644 --- a/frontend/src/views/Org/MembersPage/components/OrgIdentityTab/components/IdentitySection/IdentityKubernetesAuthForm.tsx +++ b/frontend/src/views/Org/MembersPage/components/OrgIdentityTab/components/IdentitySection/IdentityKubernetesAuthForm.tsx @@ -10,9 +10,9 @@ import { Button, FormControl, IconButton, Input, TextArea } from "@app/component import { useOrganization, useSubscription } from "@app/context"; import { useAddIdentityKubernetesAuth, - useDeleteIdentityKubernetesAuth, useGetIdentityKubernetesAuth, - useUpdateIdentityKubernetesAuth} from "@app/hooks/api"; + useUpdateIdentityKubernetesAuth +} from "@app/hooks/api"; import { IdentityAuthMethod } from "@app/hooks/api/identities"; import { IdentityTrustedIp } from "@app/hooks/api/identities/types"; import { UsePopUpState } from "@app/hooks/usePopUp"; @@ -43,7 +43,7 @@ export type FormData = z.infer; type Props = { handlePopUpOpen: (popUpName: keyof UsePopUpState<["upgradePlan"]>) => void; handlePopUpToggle: ( - popUpName: keyof UsePopUpState<["identityAuthMethod"]>, + popUpName: keyof UsePopUpState<["identityAuthMethod", "revokeAuthMethod"]>, state?: boolean ) => void; identityAuthMethodData: { @@ -64,7 +64,6 @@ export const IdentityKubernetesAuthForm = ({ const { mutateAsync: addMutateAsync } = useAddIdentityKubernetesAuth(); const { mutateAsync: updateMutateAsync } = useUpdateIdentityKubernetesAuth(); - const { mutateAsync: deleteMutateAsync } = useDeleteIdentityKubernetesAuth(); const { data } = useGetIdentityKubernetesAuth(identityAuthMethodData?.identityId ?? ""); @@ -399,7 +398,7 @@ export const IdentityKubernetesAuthForm = ({ variant="plain" onClick={() => handlePopUpToggle("identityAuthMethod", false)} > - {identityAuthMethodData?.authMethod ? "Cancel" : "Skip"} + Cancel
{identityAuthMethodData?.authMethod && ( @@ -408,14 +407,7 @@ export const IdentityKubernetesAuthForm = ({ colorSchema="danger" isLoading={isSubmitting} isDisabled={isSubmitting} - onClick={async () => { - await deleteMutateAsync({ - identityId: identityAuthMethodData.identityId, - organizationId: orgId - }); - - handlePopUpToggle("identityAuthMethod", false); - }} + onClick={() => handlePopUpToggle("revokeAuthMethod", true)} > Remove Auth Method diff --git a/frontend/src/views/Org/MembersPage/components/OrgIdentityTab/components/IdentitySection/IdentitySection.tsx b/frontend/src/views/Org/MembersPage/components/OrgIdentityTab/components/IdentitySection/IdentitySection.tsx index 5cc18ff13..5cb615ebb 100644 --- a/frontend/src/views/Org/MembersPage/components/OrgIdentityTab/components/IdentitySection/IdentitySection.tsx +++ b/frontend/src/views/Org/MembersPage/components/OrgIdentityTab/components/IdentitySection/IdentitySection.tsx @@ -15,7 +15,7 @@ import { withPermission } from "@app/hoc"; import { useDeleteIdentity } from "@app/hooks/api"; import { usePopUp } from "@app/hooks/usePopUp"; -import { IdentityAuthMethodModal } from "./IdentityAuthMethodModal"; +// import { IdentityAuthMethodModal } from "./IdentityAuthMethodModal"; import { IdentityModal } from "./IdentityModal"; import { IdentityTable } from "./IdentityTable"; import { IdentityTokenAuthTokenModal } from "./IdentityTokenAuthTokenModal"; @@ -110,11 +110,11 @@ export const IdentitySection = withPermission(
- + /> */} {/* { {isLoading && } {!isLoading && - data && - data.length > 0 && - data.map(({ identity: { id, name }, role, customRole }) => { + data?.map(({ identity: { id, name }, role, customRole }) => { return ( - + router.push(`/org/${orgId}/identities/${id}`)} + > {name} diff --git a/frontend/src/views/Org/MembersPage/components/OrgIdentityTab/components/IdentitySection/IdentityTokenAuthForm.tsx b/frontend/src/views/Org/MembersPage/components/OrgIdentityTab/components/IdentitySection/IdentityTokenAuthForm.tsx index 09e486d1d..b28af537f 100644 --- a/frontend/src/views/Org/MembersPage/components/OrgIdentityTab/components/IdentitySection/IdentityTokenAuthForm.tsx +++ b/frontend/src/views/Org/MembersPage/components/OrgIdentityTab/components/IdentitySection/IdentityTokenAuthForm.tsx @@ -9,9 +9,9 @@ import { Button, FormControl, IconButton, Input } from "@app/components/v2"; import { useOrganization, useSubscription } from "@app/context"; import { useAddIdentityTokenAuth, - useDeleteIdentityTokenAuth, useGetIdentityTokenAuth, - useUpdateIdentityTokenAuth} from "@app/hooks/api"; + useUpdateIdentityTokenAuth +} from "@app/hooks/api"; import { IdentityAuthMethod } from "@app/hooks/api/identities"; import { UsePopUpState } from "@app/hooks/usePopUp"; @@ -35,7 +35,7 @@ export type FormData = z.infer; type Props = { handlePopUpOpen: (popUpName: keyof UsePopUpState<["upgradePlan"]>) => void; handlePopUpToggle: ( - popUpName: keyof UsePopUpState<["identityAuthMethod"]>, + popUpName: keyof UsePopUpState<["identityAuthMethod", "revokeAuthMethod"]>, state?: boolean ) => void; identityAuthMethodData: { @@ -56,7 +56,6 @@ export const IdentityTokenAuthForm = ({ const { mutateAsync: addMutateAsync } = useAddIdentityTokenAuth(); const { mutateAsync: updateMutateAsync } = useUpdateIdentityTokenAuth(); - const { mutateAsync: deleteMutateAsync } = useDeleteIdentityTokenAuth(); const { data } = useGetIdentityTokenAuth(identityAuthMethodData?.identityId ?? ""); @@ -256,7 +255,7 @@ export const IdentityTokenAuthForm = ({ variant="plain" onClick={() => handlePopUpToggle("identityAuthMethod", false)} > - {identityAuthMethodData?.authMethod ? "Cancel" : "Skip"} + Cancel
{identityAuthMethodData?.authMethod && ( @@ -265,14 +264,7 @@ export const IdentityTokenAuthForm = ({ colorSchema="danger" isLoading={isSubmitting} isDisabled={isSubmitting} - onClick={async () => { - await deleteMutateAsync({ - identityId: identityAuthMethodData.identityId, - organizationId: orgId - }); - - handlePopUpToggle("identityAuthMethod", false); - }} + onClick={() => handlePopUpToggle("revokeAuthMethod", true)} > Remove Auth Method diff --git a/frontend/src/views/Org/MembersPage/components/OrgIdentityTab/components/IdentitySection/IdentityUniversalAuthForm.tsx b/frontend/src/views/Org/MembersPage/components/OrgIdentityTab/components/IdentitySection/IdentityUniversalAuthForm.tsx index be9235b37..2e3df29f2 100644 --- a/frontend/src/views/Org/MembersPage/components/OrgIdentityTab/components/IdentitySection/IdentityUniversalAuthForm.tsx +++ b/frontend/src/views/Org/MembersPage/components/OrgIdentityTab/components/IdentitySection/IdentityUniversalAuthForm.tsx @@ -10,9 +10,9 @@ import { Button, FormControl, IconButton, Input } from "@app/components/v2"; import { useOrganization, useSubscription } from "@app/context"; import { useAddIdentityUniversalAuth, - useDeleteIdentityUniversalAuth, useGetIdentityUniversalAuth, - useUpdateIdentityUniversalAuth} from "@app/hooks/api"; + useUpdateIdentityUniversalAuth +} from "@app/hooks/api"; import { IdentityAuthMethod } from "@app/hooks/api/identities"; import { IdentityTrustedIp } from "@app/hooks/api/identities/types"; import { UsePopUpState } from "@app/hooks/usePopUp"; @@ -48,7 +48,7 @@ export type FormData = yup.InferType; type Props = { handlePopUpOpen: (popUpName: keyof UsePopUpState<["upgradePlan"]>) => void; handlePopUpToggle: ( - popUpName: keyof UsePopUpState<["identityAuthMethod"]>, + popUpName: keyof UsePopUpState<["identityAuthMethod", "revokeAuthMethod"]>, state?: boolean ) => void; identityAuthMethodData: { @@ -68,7 +68,6 @@ export const IdentityUniversalAuthForm = ({ const { subscription } = useSubscription(); const { mutateAsync: addMutateAsync } = useAddIdentityUniversalAuth(); const { mutateAsync: updateMutateAsync } = useUpdateIdentityUniversalAuth(); - const { mutateAsync: deleteMutateAsync } = useDeleteIdentityUniversalAuth(); const { data } = useGetIdentityUniversalAuth(identityAuthMethodData?.identityId ?? ""); const { @@ -385,7 +384,7 @@ export const IdentityUniversalAuthForm = ({ variant="plain" onClick={() => handlePopUpToggle("identityAuthMethod", false)} > - {identityAuthMethodData?.authMethod ? "Cancel" : "Skip"} + Cancel {identityAuthMethodData?.authMethod && ( @@ -394,14 +393,7 @@ export const IdentityUniversalAuthForm = ({ colorSchema="danger" isLoading={isSubmitting} isDisabled={isSubmitting} - onClick={async () => { - await deleteMutateAsync({ - identityId: identityAuthMethodData.identityId, - organizationId: orgId - }); - - handlePopUpToggle("identityAuthMethod", false); - }} + onClick={() => handlePopUpToggle("revokeAuthMethod", true)} > Remove Auth Method