mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-08 03:27:38 +00:00
Make fixes based on review
This commit is contained in:
@@ -816,8 +816,7 @@ export const registerRoutes = async (
|
|||||||
});
|
});
|
||||||
const identityAccessTokenService = identityAccessTokenServiceFactory({
|
const identityAccessTokenService = identityAccessTokenServiceFactory({
|
||||||
identityAccessTokenDAL,
|
identityAccessTokenDAL,
|
||||||
identityOrgMembershipDAL,
|
identityOrgMembershipDAL
|
||||||
permissionService
|
|
||||||
});
|
});
|
||||||
const identityProjectService = identityProjectServiceFactory({
|
const identityProjectService = identityProjectServiceFactory({
|
||||||
permissionService,
|
permissionService,
|
||||||
|
|||||||
@@ -2,8 +2,6 @@ import { z } from "zod";
|
|||||||
|
|
||||||
import { UNIVERSAL_AUTH } from "@app/lib/api-docs";
|
import { UNIVERSAL_AUTH } from "@app/lib/api-docs";
|
||||||
import { writeLimit } from "@app/server/config/rateLimiter";
|
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) => {
|
export const registerIdentityAccessTokenRouter = async (server: FastifyZodProvider) => {
|
||||||
server.route({
|
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"
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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({
|
server.route({
|
||||||
method: "POST",
|
method: "POST",
|
||||||
url: "/token-auth/identities/:identityId/tokens",
|
url: "/token-auth/identities/:identityId/tokens",
|
||||||
@@ -284,7 +293,7 @@ export const registerIdentityTokenAuthRouter = async (server: FastifyZodProvider
|
|||||||
},
|
},
|
||||||
handler: async (req) => {
|
handler: async (req) => {
|
||||||
const { identityTokenAuth, accessToken, identityAccessToken, identityMembershipOrg } =
|
const { identityTokenAuth, accessToken, identityAccessToken, identityMembershipOrg } =
|
||||||
await server.services.identityTokenAuth.createTokenTokenAuth({
|
await server.services.identityTokenAuth.createTokenAuthToken({
|
||||||
actor: req.permission.type,
|
actor: req.permission.type,
|
||||||
actorId: req.permission.id,
|
actorId: req.permission.id,
|
||||||
actorAuthMethod: req.permission.authMethod,
|
actorAuthMethod: req.permission.authMethod,
|
||||||
@@ -342,7 +351,7 @@ export const registerIdentityTokenAuthRouter = async (server: FastifyZodProvider
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
handler: async (req) => {
|
handler: async (req) => {
|
||||||
const { tokens, identityMembershipOrg } = await server.services.identityTokenAuth.getTokensTokenAuth({
|
const { tokens, identityMembershipOrg } = await server.services.identityTokenAuth.getTokenAuthTokens({
|
||||||
actor: req.permission.type,
|
actor: req.permission.type,
|
||||||
actorId: req.permission.id,
|
actorId: req.permission.id,
|
||||||
actorAuthMethod: req.permission.authMethod,
|
actorAuthMethod: req.permission.authMethod,
|
||||||
@@ -368,7 +377,7 @@ export const registerIdentityTokenAuthRouter = async (server: FastifyZodProvider
|
|||||||
|
|
||||||
server.route({
|
server.route({
|
||||||
method: "PATCH",
|
method: "PATCH",
|
||||||
url: "/token-auth/identities/:identityId/tokens/:tokenId",
|
url: "/token-auth/tokens/:tokenId",
|
||||||
config: {
|
config: {
|
||||||
rateLimit: writeLimit
|
rateLimit: writeLimit
|
||||||
},
|
},
|
||||||
@@ -381,7 +390,6 @@ export const registerIdentityTokenAuthRouter = async (server: FastifyZodProvider
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
params: z.object({
|
params: z.object({
|
||||||
identityId: z.string(),
|
|
||||||
tokenId: z.string()
|
tokenId: z.string()
|
||||||
}),
|
}),
|
||||||
body: z.object({
|
body: z.object({
|
||||||
@@ -394,12 +402,11 @@ export const registerIdentityTokenAuthRouter = async (server: FastifyZodProvider
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
handler: async (req) => {
|
handler: async (req) => {
|
||||||
const { token, identityMembershipOrg } = await server.services.identityTokenAuth.updateTokenTokenAuth({
|
const { token, identityMembershipOrg } = await server.services.identityTokenAuth.updateTokenAuthToken({
|
||||||
actor: req.permission.type,
|
actor: req.permission.type,
|
||||||
actorId: req.permission.id,
|
actorId: req.permission.id,
|
||||||
actorAuthMethod: req.permission.authMethod,
|
actorAuthMethod: req.permission.authMethod,
|
||||||
actorOrgId: req.permission.orgId,
|
actorOrgId: req.permission.orgId,
|
||||||
identityId: req.params.identityId,
|
|
||||||
tokenId: req.params.tokenId,
|
tokenId: req.params.tokenId,
|
||||||
...req.body
|
...req.body
|
||||||
});
|
});
|
||||||
@@ -410,7 +417,7 @@ export const registerIdentityTokenAuthRouter = async (server: FastifyZodProvider
|
|||||||
event: {
|
event: {
|
||||||
type: EventType.UPDATE_TOKEN_IDENTITY_TOKEN_AUTH,
|
type: EventType.UPDATE_TOKEN_IDENTITY_TOKEN_AUTH,
|
||||||
metadata: {
|
metadata: {
|
||||||
identityId: req.params.identityId,
|
identityId: token.identityId,
|
||||||
tokenId: token.id,
|
tokenId: token.id,
|
||||||
name: req.body.name
|
name: req.body.name
|
||||||
}
|
}
|
||||||
@@ -420,4 +427,42 @@ export const registerIdentityTokenAuthRouter = async (server: FastifyZodProvider
|
|||||||
return { token };
|
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"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,9 +1,6 @@
|
|||||||
import { ForbiddenError } from "@casl/ability";
|
|
||||||
import jwt, { JwtPayload } from "jsonwebtoken";
|
import jwt, { JwtPayload } from "jsonwebtoken";
|
||||||
|
|
||||||
import { TableName, TIdentityAccessTokens } from "@app/db/schemas";
|
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 { getConfig } from "@app/lib/config/env";
|
||||||
import { BadRequestError, UnauthorizedError } from "@app/lib/errors";
|
import { BadRequestError, UnauthorizedError } from "@app/lib/errors";
|
||||||
import { checkIPAgainstBlocklist, TIp } from "@app/lib/ip";
|
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 { AuthTokenType } from "../auth/auth-type";
|
||||||
import { TIdentityOrgDALFactory } from "../identity/identity-org-dal";
|
import { TIdentityOrgDALFactory } from "../identity/identity-org-dal";
|
||||||
import { TIdentityAccessTokenDALFactory } from "./identity-access-token-dal";
|
import { TIdentityAccessTokenDALFactory } from "./identity-access-token-dal";
|
||||||
import {
|
import { TIdentityAccessTokenJwtPayload, TRenewAccessTokenDTO } from "./identity-access-token-types";
|
||||||
TIdentityAccessTokenJwtPayload,
|
|
||||||
TRenewAccessTokenDTO,
|
|
||||||
TRevokeAccessTokenByIdDTO
|
|
||||||
} from "./identity-access-token-types";
|
|
||||||
|
|
||||||
type TIdentityAccessTokenServiceFactoryDep = {
|
type TIdentityAccessTokenServiceFactoryDep = {
|
||||||
identityAccessTokenDAL: TIdentityAccessTokenDALFactory;
|
identityAccessTokenDAL: TIdentityAccessTokenDALFactory;
|
||||||
identityOrgMembershipDAL: TIdentityOrgDALFactory;
|
identityOrgMembershipDAL: TIdentityOrgDALFactory;
|
||||||
permissionService: Pick<TPermissionServiceFactory, "getOrgPermission">;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export type TIdentityAccessTokenServiceFactory = ReturnType<typeof identityAccessTokenServiceFactory>;
|
export type TIdentityAccessTokenServiceFactory = ReturnType<typeof identityAccessTokenServiceFactory>;
|
||||||
|
|
||||||
export const identityAccessTokenServiceFactory = ({
|
export const identityAccessTokenServiceFactory = ({
|
||||||
identityAccessTokenDAL,
|
identityAccessTokenDAL,
|
||||||
identityOrgMembershipDAL,
|
identityOrgMembershipDAL
|
||||||
permissionService
|
|
||||||
}: TIdentityAccessTokenServiceFactoryDep) => {
|
}: TIdentityAccessTokenServiceFactoryDep) => {
|
||||||
const validateAccessTokenExp = async (identityAccessToken: TIdentityAccessTokens) => {
|
const validateAccessTokenExp = async (identityAccessToken: TIdentityAccessTokens) => {
|
||||||
const {
|
const {
|
||||||
@@ -147,43 +138,6 @@ export const identityAccessTokenServiceFactory = ({
|
|||||||
return { revokedToken };
|
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 fnValidateIdentityAccessToken = async (token: TIdentityAccessTokenJwtPayload, ipAddress?: string) => {
|
||||||
const identityAccessToken = await identityAccessTokenDAL.findOne({
|
const identityAccessToken = await identityAccessTokenDAL.findOne({
|
||||||
[`${TableName.IdentityAccessToken}.id` as "id"]: token.identityAccessTokenId,
|
[`${TableName.IdentityAccessToken}.id` as "id"]: token.identityAccessTokenId,
|
||||||
@@ -221,5 +175,5 @@ export const identityAccessTokenServiceFactory = ({
|
|||||||
return { ...identityAccessToken, orgId: identityOrgMembership.orgId };
|
return { ...identityAccessToken, orgId: identityOrgMembership.orgId };
|
||||||
};
|
};
|
||||||
|
|
||||||
return { renewAccessToken, revokeAccessToken, revokeAccessTokenById, fnValidateIdentityAccessToken };
|
return { renewAccessToken, revokeAccessToken, fnValidateIdentityAccessToken };
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
import { TProjectPermission } from "@app/lib/types";
|
|
||||||
|
|
||||||
export type TRenewAccessTokenDTO = {
|
export type TRenewAccessTokenDTO = {
|
||||||
accessToken: string;
|
accessToken: string;
|
||||||
};
|
};
|
||||||
@@ -10,7 +8,3 @@ export type TIdentityAccessTokenJwtPayload = {
|
|||||||
identityAccessTokenId: string;
|
identityAccessTokenId: string;
|
||||||
authTokenType: string;
|
authTokenType: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type TRevokeAccessTokenByIdDTO = {
|
|
||||||
tokenId: string;
|
|
||||||
} & Omit<TProjectPermission, "projectId">;
|
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
import { ForbiddenError } from "@casl/ability";
|
import { ForbiddenError } from "@casl/ability";
|
||||||
import jwt from "jsonwebtoken";
|
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 { TLicenseServiceFactory } from "@app/ee/services/license/license-service";
|
||||||
import { OrgPermissionActions, OrgPermissionSubjects } from "@app/ee/services/permission/org-permission";
|
import { OrgPermissionActions, OrgPermissionSubjects } from "@app/ee/services/permission/org-permission";
|
||||||
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
|
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
|
||||||
import { isAtLeastAsPrivileged } from "@app/lib/casl";
|
import { isAtLeastAsPrivileged } from "@app/lib/casl";
|
||||||
import { getConfig } from "@app/lib/config/env";
|
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 { extractIPDetails, isValidIpOrCidr } from "@app/lib/ip";
|
||||||
|
|
||||||
import { ActorType, AuthTokenType } from "../auth/auth-type";
|
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 { TIdentityTokenAuthDALFactory } from "./identity-token-auth-dal";
|
||||||
import {
|
import {
|
||||||
TAttachTokenAuthDTO,
|
TAttachTokenAuthDTO,
|
||||||
TCreateTokenTokenAuthDTO,
|
TCreateTokenAuthTokenDTO,
|
||||||
TGetTokenAuthDTO,
|
TGetTokenAuthDTO,
|
||||||
TGetTokensTokenAuthDTO,
|
TGetTokenAuthTokensDTO,
|
||||||
TRevokeTokenAuthDTO,
|
TRevokeTokenAuthDTO,
|
||||||
|
TRevokeTokenAuthTokenDTO,
|
||||||
TUpdateTokenAuthDTO,
|
TUpdateTokenAuthDTO,
|
||||||
TUpdateTokenTokenAuthDTO
|
TUpdateTokenAuthTokenDTO
|
||||||
} from "./identity-token-auth-types";
|
} from "./identity-token-auth-types";
|
||||||
|
|
||||||
type TIdentityTokenAuthServiceFactoryDep = {
|
type TIdentityTokenAuthServiceFactoryDep = {
|
||||||
@@ -33,7 +34,10 @@ type TIdentityTokenAuthServiceFactoryDep = {
|
|||||||
>;
|
>;
|
||||||
identityDAL: Pick<TIdentityDALFactory, "updateById">;
|
identityDAL: Pick<TIdentityDALFactory, "updateById">;
|
||||||
identityOrgMembershipDAL: Pick<TIdentityOrgDALFactory, "findOne">;
|
identityOrgMembershipDAL: Pick<TIdentityOrgDALFactory, "findOne">;
|
||||||
identityAccessTokenDAL: Pick<TIdentityAccessTokenDALFactory, "create" | "find" | "update">;
|
identityAccessTokenDAL: Pick<
|
||||||
|
TIdentityAccessTokenDALFactory,
|
||||||
|
"create" | "find" | "update" | "findById" | "findOne" | "updateById"
|
||||||
|
>;
|
||||||
permissionService: Pick<TPermissionServiceFactory, "getOrgPermission">;
|
permissionService: Pick<TPermissionServiceFactory, "getOrgPermission">;
|
||||||
licenseService: Pick<TLicenseServiceFactory, "getPlan">;
|
licenseService: Pick<TLicenseServiceFactory, "getPlan">;
|
||||||
};
|
};
|
||||||
@@ -243,7 +247,7 @@ export const identityTokenAuthServiceFactory = ({
|
|||||||
);
|
);
|
||||||
const hasPriviledge = isAtLeastAsPrivileged(permission, rolePermission);
|
const hasPriviledge = isAtLeastAsPrivileged(permission, rolePermission);
|
||||||
if (!hasPriviledge)
|
if (!hasPriviledge)
|
||||||
throw new ForbiddenRequestError({
|
throw new UnauthorizedError({
|
||||||
message: "Failed to revoke Token Auth of identity with more privileged role"
|
message: "Failed to revoke Token Auth of identity with more privileged role"
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -255,14 +259,14 @@ export const identityTokenAuthServiceFactory = ({
|
|||||||
return revokedIdentityTokenAuth;
|
return revokedIdentityTokenAuth;
|
||||||
};
|
};
|
||||||
|
|
||||||
const createTokenTokenAuth = async ({
|
const createTokenAuthToken = async ({
|
||||||
identityId,
|
identityId,
|
||||||
actorId,
|
actorId,
|
||||||
actor,
|
actor,
|
||||||
actorAuthMethod,
|
actorAuthMethod,
|
||||||
actorOrgId,
|
actorOrgId,
|
||||||
name
|
name
|
||||||
}: TCreateTokenTokenAuthDTO) => {
|
}: TCreateTokenAuthTokenDTO) => {
|
||||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
|
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
|
||||||
if (!identityMembershipOrg) throw new BadRequestError({ message: "Failed to find identity" });
|
if (!identityMembershipOrg) throw new BadRequestError({ message: "Failed to find identity" });
|
||||||
if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.TOKEN_AUTH)
|
if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.TOKEN_AUTH)
|
||||||
@@ -328,7 +332,7 @@ export const identityTokenAuthServiceFactory = ({
|
|||||||
return { accessToken, identityTokenAuth, identityAccessToken, identityMembershipOrg };
|
return { accessToken, identityTokenAuth, identityAccessToken, identityMembershipOrg };
|
||||||
};
|
};
|
||||||
|
|
||||||
const getTokensTokenAuth = async ({
|
const getTokenAuthTokens = async ({
|
||||||
identityId,
|
identityId,
|
||||||
offset = 0,
|
offset = 0,
|
||||||
limit = 20,
|
limit = 20,
|
||||||
@@ -336,7 +340,7 @@ export const identityTokenAuthServiceFactory = ({
|
|||||||
actor,
|
actor,
|
||||||
actorAuthMethod,
|
actorAuthMethod,
|
||||||
actorOrgId
|
actorOrgId
|
||||||
}: TGetTokensTokenAuthDTO) => {
|
}: TGetTokenAuthTokensDTO) => {
|
||||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
|
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
|
||||||
if (!identityMembershipOrg) throw new BadRequestError({ message: "Failed to find identity" });
|
if (!identityMembershipOrg) throw new BadRequestError({ message: "Failed to find identity" });
|
||||||
if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.TOKEN_AUTH)
|
if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.TOKEN_AUTH)
|
||||||
@@ -350,20 +354,7 @@ export const identityTokenAuthServiceFactory = ({
|
|||||||
actorAuthMethod,
|
actorAuthMethod,
|
||||||
actorOrgId
|
actorOrgId
|
||||||
);
|
);
|
||||||
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.Identity);
|
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, 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"
|
|
||||||
});
|
|
||||||
|
|
||||||
const tokens = await identityAccessTokenDAL.find(
|
const tokens = await identityAccessTokenDAL.find(
|
||||||
{
|
{
|
||||||
@@ -375,16 +366,17 @@ export const identityTokenAuthServiceFactory = ({
|
|||||||
return { tokens, identityMembershipOrg };
|
return { tokens, identityMembershipOrg };
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateTokenTokenAuth = async ({
|
const updateTokenAuthToken = async ({
|
||||||
identityId,
|
|
||||||
tokenId,
|
tokenId,
|
||||||
name,
|
name,
|
||||||
actorId,
|
actorId,
|
||||||
actor,
|
actor,
|
||||||
actorAuthMethod,
|
actorAuthMethod,
|
||||||
actorOrgId
|
actorOrgId
|
||||||
}: TUpdateTokenTokenAuthDTO) => {
|
}: TUpdateTokenAuthTokenDTO) => {
|
||||||
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
|
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) throw new BadRequestError({ message: "Failed to find identity" });
|
||||||
if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.TOKEN_AUTH)
|
if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.TOKEN_AUTH)
|
||||||
throw new BadRequestError({
|
throw new BadRequestError({
|
||||||
@@ -414,7 +406,7 @@ export const identityTokenAuthServiceFactory = ({
|
|||||||
|
|
||||||
const [token] = await identityAccessTokenDAL.update(
|
const [token] = await identityAccessTokenDAL.update(
|
||||||
{
|
{
|
||||||
identityId,
|
identityId: foundToken.identityId,
|
||||||
id: tokenId
|
id: tokenId
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -425,13 +417,54 @@ export const identityTokenAuthServiceFactory = ({
|
|||||||
return { token, identityMembershipOrg };
|
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 {
|
return {
|
||||||
attachTokenAuth,
|
attachTokenAuth,
|
||||||
updateTokenAuth,
|
updateTokenAuth,
|
||||||
getTokenAuth,
|
getTokenAuth,
|
||||||
revokeIdentityTokenAuth,
|
revokeIdentityTokenAuth,
|
||||||
createTokenTokenAuth,
|
createTokenAuthToken,
|
||||||
getTokensTokenAuth,
|
getTokenAuthTokens,
|
||||||
updateTokenTokenAuth
|
updateTokenAuthToken,
|
||||||
|
revokeTokenAuthToken
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -24,19 +24,22 @@ export type TRevokeTokenAuthDTO = {
|
|||||||
identityId: string;
|
identityId: string;
|
||||||
} & Omit<TProjectPermission, "projectId">;
|
} & Omit<TProjectPermission, "projectId">;
|
||||||
|
|
||||||
export type TCreateTokenTokenAuthDTO = {
|
export type TCreateTokenAuthTokenDTO = {
|
||||||
identityId: string;
|
identityId: string;
|
||||||
name?: string;
|
name?: string;
|
||||||
} & Omit<TProjectPermission, "projectId">;
|
} & Omit<TProjectPermission, "projectId">;
|
||||||
|
|
||||||
export type TGetTokensTokenAuthDTO = {
|
export type TGetTokenAuthTokensDTO = {
|
||||||
identityId: string;
|
identityId: string;
|
||||||
offset: number;
|
offset: number;
|
||||||
limit: number;
|
limit: number;
|
||||||
} & Omit<TProjectPermission, "projectId">;
|
} & Omit<TProjectPermission, "projectId">;
|
||||||
|
|
||||||
export type TUpdateTokenTokenAuthDTO = {
|
export type TUpdateTokenAuthTokenDTO = {
|
||||||
identityId: string;
|
|
||||||
tokenId: string;
|
tokenId: string;
|
||||||
name?: string;
|
name?: string;
|
||||||
} & Omit<TProjectPermission, "projectId">;
|
} & Omit<TProjectPermission, "projectId">;
|
||||||
|
|
||||||
|
export type TRevokeTokenAuthTokenDTO = {
|
||||||
|
tokenId: string;
|
||||||
|
} & Omit<TProjectPermission, "projectId">;
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { TLicenseServiceFactory } from "@app/ee/services/license/license-service
|
|||||||
import { OrgPermissionActions, OrgPermissionSubjects } from "@app/ee/services/permission/org-permission";
|
import { OrgPermissionActions, OrgPermissionSubjects } from "@app/ee/services/permission/org-permission";
|
||||||
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
|
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
|
||||||
import { isAtLeastAsPrivileged } from "@app/lib/casl";
|
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 { TOrgPermission } from "@app/lib/types";
|
||||||
import { TIdentityProjectDALFactory } from "@app/services/identity-project/identity-project-dal";
|
import { TIdentityProjectDALFactory } from "@app/services/identity-project/identity-project-dal";
|
||||||
|
|
||||||
@@ -213,7 +213,7 @@ export const identityServiceFactory = ({
|
|||||||
actorOrgId
|
actorOrgId
|
||||||
}: TListProjectIdentitiesByIdentityIdDTO) => {
|
}: TListProjectIdentitiesByIdentityIdDTO) => {
|
||||||
const identityOrgMembership = await identityOrgMembershipDAL.findOne({ identityId });
|
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(
|
const { permission } = await permissionService.getOrgPermission(
|
||||||
actor,
|
actor,
|
||||||
|
|||||||
@@ -17,16 +17,16 @@ export {
|
|||||||
useDeleteIdentityKubernetesAuth,
|
useDeleteIdentityKubernetesAuth,
|
||||||
useDeleteIdentityTokenAuth,
|
useDeleteIdentityTokenAuth,
|
||||||
useDeleteIdentityUniversalAuth,
|
useDeleteIdentityUniversalAuth,
|
||||||
|
useRevokeIdentityTokenAuthToken,
|
||||||
useRevokeIdentityUniversalAuthClientSecret,
|
useRevokeIdentityUniversalAuthClientSecret,
|
||||||
useRevokeToken,
|
|
||||||
useUpdateIdentity,
|
useUpdateIdentity,
|
||||||
useUpdateIdentityAwsAuth,
|
useUpdateIdentityAwsAuth,
|
||||||
useUpdateIdentityAzureAuth,
|
useUpdateIdentityAzureAuth,
|
||||||
useUpdateIdentityGcpAuth,
|
useUpdateIdentityGcpAuth,
|
||||||
useUpdateIdentityKubernetesAuth,
|
useUpdateIdentityKubernetesAuth,
|
||||||
useUpdateIdentityTokenAuth,
|
useUpdateIdentityTokenAuth,
|
||||||
useUpdateIdentityUniversalAuth,
|
useUpdateIdentityTokenAuthToken,
|
||||||
useUpdateTokenIdentityTokenAuth} from "./mutations";
|
useUpdateIdentityUniversalAuth} from "./mutations";
|
||||||
export {
|
export {
|
||||||
useGetIdentityAwsAuth,
|
useGetIdentityAwsAuth,
|
||||||
useGetIdentityAzureAuth,
|
useGetIdentityAzureAuth,
|
||||||
@@ -37,4 +37,5 @@ export {
|
|||||||
useGetIdentityTokenAuth,
|
useGetIdentityTokenAuth,
|
||||||
useGetIdentityTokensTokenAuth,
|
useGetIdentityTokensTokenAuth,
|
||||||
useGetIdentityUniversalAuth,
|
useGetIdentityUniversalAuth,
|
||||||
useGetIdentityUniversalAuthClientSecrets} from "./queries";
|
useGetIdentityUniversalAuthClientSecrets
|
||||||
|
} from "./queries";
|
||||||
|
|||||||
@@ -42,7 +42,8 @@ import {
|
|||||||
UpdateIdentityKubernetesAuthDTO,
|
UpdateIdentityKubernetesAuthDTO,
|
||||||
UpdateIdentityTokenAuthDTO,
|
UpdateIdentityTokenAuthDTO,
|
||||||
UpdateIdentityUniversalAuthDTO,
|
UpdateIdentityUniversalAuthDTO,
|
||||||
UpdateTokenIdentityTokenAuthDTO} from "./types";
|
UpdateTokenIdentityTokenAuthDTO
|
||||||
|
} from "./types";
|
||||||
|
|
||||||
export const useCreateIdentity = () => {
|
export const useCreateIdentity = () => {
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
@@ -706,14 +707,14 @@ export const useCreateTokenIdentityTokenAuth = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useUpdateTokenIdentityTokenAuth = () => {
|
export const useUpdateIdentityTokenAuthToken = () => {
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
return useMutation<IdentityAccessToken, {}, UpdateTokenIdentityTokenAuthDTO>({
|
return useMutation<IdentityAccessToken, {}, UpdateTokenIdentityTokenAuthDTO>({
|
||||||
mutationFn: async ({ identityId, tokenId, name }) => {
|
mutationFn: async ({ tokenId, name }) => {
|
||||||
const {
|
const {
|
||||||
data: { token }
|
data: { token }
|
||||||
} = await apiRequest.patch<{ token: IdentityAccessToken }>(
|
} = await apiRequest.patch<{ token: IdentityAccessToken }>(
|
||||||
`/api/v1/auth/token-auth/identities/${identityId}/tokens/${tokenId}`,
|
`/api/v1/auth/token-auth/tokens/${tokenId}`,
|
||||||
{
|
{
|
||||||
name
|
name
|
||||||
}
|
}
|
||||||
@@ -727,13 +728,13 @@ export const useUpdateTokenIdentityTokenAuth = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useRevokeToken = () => {
|
export const useRevokeIdentityTokenAuthToken = () => {
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
return useMutation<RevokeTokenRes, {}, RevokeTokenDTO>({
|
return useMutation<RevokeTokenRes, {}, RevokeTokenDTO>({
|
||||||
mutationFn: async ({ tokenId }) => {
|
mutationFn: async ({ tokenId }) => {
|
||||||
const { data } = await apiRequest.post<RevokeTokenRes>("/api/v1/auth/token/revoke-by-id", {
|
const { data } = await apiRequest.post<RevokeTokenRes>(
|
||||||
tokenId
|
`/api/v1/auth/token-auth/tokens/${tokenId}/revoke`
|
||||||
});
|
);
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -21,9 +21,8 @@ import { withPermission } from "@app/hoc";
|
|||||||
import {
|
import {
|
||||||
useDeleteIdentity,
|
useDeleteIdentity,
|
||||||
useGetIdentityById,
|
useGetIdentityById,
|
||||||
useRevokeIdentityUniversalAuthClientSecret,
|
useRevokeIdentityTokenAuthToken,
|
||||||
useRevokeToken
|
useRevokeIdentityUniversalAuthClientSecret} from "@app/hooks/api";
|
||||||
} from "@app/hooks/api";
|
|
||||||
import { usePopUp } from "@app/hooks/usePopUp";
|
import { usePopUp } from "@app/hooks/usePopUp";
|
||||||
|
|
||||||
import { IdentityAuthMethodModal } from "../MembersPage/components/OrgIdentityTab/components/IdentitySection/IdentityAuthMethodModal";
|
import { IdentityAuthMethodModal } from "../MembersPage/components/OrgIdentityTab/components/IdentitySection/IdentityAuthMethodModal";
|
||||||
@@ -35,7 +34,8 @@ import {
|
|||||||
IdentityDetailsSection,
|
IdentityDetailsSection,
|
||||||
IdentityProjectsSection,
|
IdentityProjectsSection,
|
||||||
IdentityTokenListModal,
|
IdentityTokenListModal,
|
||||||
IdentityTokenModal} from "./components";
|
IdentityTokenModal
|
||||||
|
} from "./components";
|
||||||
|
|
||||||
export const IdentityPage = withPermission(
|
export const IdentityPage = withPermission(
|
||||||
() => {
|
() => {
|
||||||
@@ -45,13 +45,14 @@ export const IdentityPage = withPermission(
|
|||||||
const orgId = currentOrg?.id || "";
|
const orgId = currentOrg?.id || "";
|
||||||
const { data } = useGetIdentityById(identityId);
|
const { data } = useGetIdentityById(identityId);
|
||||||
const { mutateAsync: deleteIdentity } = useDeleteIdentity();
|
const { mutateAsync: deleteIdentity } = useDeleteIdentity();
|
||||||
const { mutateAsync: revokeToken } = useRevokeToken();
|
const { mutateAsync: revokeToken } = useRevokeIdentityTokenAuthToken();
|
||||||
const { mutateAsync: revokeClientSecret } = useRevokeIdentityUniversalAuthClientSecret();
|
const { mutateAsync: revokeClientSecret } = useRevokeIdentityUniversalAuthClientSecret();
|
||||||
|
|
||||||
const { popUp, handlePopUpOpen, handlePopUpClose, handlePopUpToggle } = usePopUp([
|
const { popUp, handlePopUpOpen, handlePopUpClose, handlePopUpToggle } = usePopUp([
|
||||||
"identity",
|
"identity",
|
||||||
"deleteIdentity",
|
"deleteIdentity",
|
||||||
"identityAuthMethod",
|
"identityAuthMethod",
|
||||||
|
"revokeAuthMethod",
|
||||||
"token",
|
"token",
|
||||||
"tokenList",
|
"tokenList",
|
||||||
"revokeToken",
|
"revokeToken",
|
||||||
|
|||||||
-12
@@ -66,18 +66,6 @@ export const IdentityAuthenticationSection = ({ identityId, handlePopUpOpen }: P
|
|||||||
<div className="py-4">
|
<div className="py-4">
|
||||||
<div className="flex justify-between">
|
<div className="flex justify-between">
|
||||||
<p className="text-sm font-semibold text-mineshaft-300">Auth Method</p>
|
<p className="text-sm font-semibold text-mineshaft-300">Auth Method</p>
|
||||||
{/* <Button
|
|
||||||
variant="link"
|
|
||||||
onClick={() => {
|
|
||||||
handlePopUpOpen("identityAuthMethod", {
|
|
||||||
identityId,
|
|
||||||
name: data.identity.name,
|
|
||||||
authMethod: data.identity.authMethod
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Manage
|
|
||||||
</Button> */}
|
|
||||||
</div>
|
</div>
|
||||||
<p className="text-sm text-mineshaft-300">
|
<p className="text-sm text-mineshaft-300">
|
||||||
{data.identity.authMethod
|
{data.identity.authMethod
|
||||||
|
|||||||
+22
-2
@@ -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 { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
import { format } from "date-fns";
|
import { format } from "date-fns";
|
||||||
|
|
||||||
import { OrgPermissionCan } from "@app/components/permissions";
|
import { OrgPermissionCan } from "@app/components/permissions";
|
||||||
import { Button, IconButton, Tooltip } from "@app/components/v2";
|
import { Button, IconButton, Tooltip } from "@app/components/v2";
|
||||||
import { OrgPermissionActions, OrgPermissionSubjects } from "@app/context";
|
import { OrgPermissionActions, OrgPermissionSubjects } from "@app/context";
|
||||||
|
import { useTimedReset } from "@app/hooks";
|
||||||
import {
|
import {
|
||||||
useGetIdentityById,
|
useGetIdentityById,
|
||||||
useGetIdentityUniversalAuth,
|
useGetIdentityUniversalAuth,
|
||||||
@@ -25,6 +26,10 @@ type Props = {
|
|||||||
const SHOW_LIMIT = 3;
|
const SHOW_LIMIT = 3;
|
||||||
|
|
||||||
export const IdentityClientSecrets = ({ identityId, handlePopUpOpen }: Props) => {
|
export const IdentityClientSecrets = ({ identityId, handlePopUpOpen }: Props) => {
|
||||||
|
const [copyTextClientId, isCopyingClientId, setCopyTextClientId] = useTimedReset<string>({
|
||||||
|
initialState: "Copy Client ID to clipboard"
|
||||||
|
});
|
||||||
|
|
||||||
const { data } = useGetIdentityById(identityId);
|
const { data } = useGetIdentityById(identityId);
|
||||||
const { data: identityUniversalAuth } = useGetIdentityUniversalAuth(identityId);
|
const { data: identityUniversalAuth } = useGetIdentityUniversalAuth(identityId);
|
||||||
const { data: clientSecrets } = useGetIdentityUniversalAuthClientSecrets(identityId);
|
const { data: clientSecrets } = useGetIdentityUniversalAuthClientSecrets(identityId);
|
||||||
@@ -32,7 +37,22 @@ export const IdentityClientSecrets = ({ identityId, handlePopUpOpen }: Props) =>
|
|||||||
<div>
|
<div>
|
||||||
<div className="mb-4">
|
<div className="mb-4">
|
||||||
<p className="text-sm font-semibold text-mineshaft-300">Client ID</p>
|
<p className="text-sm font-semibold text-mineshaft-300">Client ID</p>
|
||||||
<p className="text-sm text-mineshaft-300">{identityUniversalAuth?.clientId ?? ""}</p>
|
<div className="flex align-top">
|
||||||
|
<p className="text-sm text-mineshaft-300">{identityUniversalAuth?.clientId ?? ""}</p>
|
||||||
|
<Tooltip content={copyTextClientId}>
|
||||||
|
<IconButton
|
||||||
|
ariaLabel="copy icon"
|
||||||
|
variant="plain"
|
||||||
|
className="group relative ml-2"
|
||||||
|
onClick={() => {
|
||||||
|
navigator.clipboard.writeText(identityUniversalAuth?.clientId ?? "");
|
||||||
|
setCopyTextClientId("Copied");
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<FontAwesomeIcon icon={isCopyingClientId ? faCheck : faCopy} />
|
||||||
|
</IconButton>
|
||||||
|
</Tooltip>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{clientSecrets?.length ? (
|
{clientSecrets?.length ? (
|
||||||
<div className="flex justify-between">
|
<div className="flex justify-between">
|
||||||
|
|||||||
+13
-11
@@ -86,17 +86,19 @@ export const IdentityTokens = ({ identityId, handlePopUpOpen }: Props) => {
|
|||||||
>
|
>
|
||||||
Edit Token
|
Edit Token
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
<DropdownMenuItem
|
{!token.isAccessTokenRevoked && (
|
||||||
onClick={async () => {
|
<DropdownMenuItem
|
||||||
handlePopUpOpen("revokeToken", {
|
onClick={async () => {
|
||||||
identityId,
|
handlePopUpOpen("revokeToken", {
|
||||||
tokenId: token.id,
|
identityId,
|
||||||
name: token.name
|
tokenId: token.id,
|
||||||
});
|
name: token.name
|
||||||
}}
|
});
|
||||||
>
|
}}
|
||||||
Revoke Token
|
>
|
||||||
</DropdownMenuItem>
|
Revoke Token
|
||||||
|
</DropdownMenuItem>
|
||||||
|
)}
|
||||||
</DropdownMenuContent>
|
</DropdownMenuContent>
|
||||||
</DropdownMenu>
|
</DropdownMenu>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -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 { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
|
|
||||||
import { OrgPermissionCan } from "@app/components/permissions";
|
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 { OrgPermissionActions, OrgPermissionSubjects } from "@app/context";
|
||||||
|
import { useTimedReset } from "@app/hooks";
|
||||||
import { useGetIdentityById } from "@app/hooks/api";
|
import { useGetIdentityById } from "@app/hooks/api";
|
||||||
import { UsePopUpState } from "@app/hooks/usePopUp";
|
import { UsePopUpState } from "@app/hooks/usePopUp";
|
||||||
|
|
||||||
@@ -16,6 +17,10 @@ type Props = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const IdentityDetailsSection = ({ identityId, handlePopUpOpen }: Props) => {
|
export const IdentityDetailsSection = ({ identityId, handlePopUpOpen }: Props) => {
|
||||||
|
const [copyTextId, isCopyingId, setCopyTextId] = useTimedReset<string>({
|
||||||
|
initialState: "Copy ID to clipboard"
|
||||||
|
});
|
||||||
|
|
||||||
const { data } = useGetIdentityById(identityId);
|
const { data } = useGetIdentityById(identityId);
|
||||||
return data ? (
|
return data ? (
|
||||||
<div className="rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
|
<div className="rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
|
||||||
@@ -49,7 +54,22 @@ export const IdentityDetailsSection = ({ identityId, handlePopUpOpen }: Props) =
|
|||||||
<div className="pt-4">
|
<div className="pt-4">
|
||||||
<div className="mb-4">
|
<div className="mb-4">
|
||||||
<p className="text-sm font-semibold text-mineshaft-300">ID</p>
|
<p className="text-sm font-semibold text-mineshaft-300">ID</p>
|
||||||
<p className="text-sm text-mineshaft-300">{data.identity.id}</p>
|
<div className="flex align-top">
|
||||||
|
<p className="text-sm text-mineshaft-300">{data.identity.id}</p>
|
||||||
|
<Tooltip content={copyTextId}>
|
||||||
|
<IconButton
|
||||||
|
ariaLabel="copy icon"
|
||||||
|
variant="plain"
|
||||||
|
className="group relative ml-2"
|
||||||
|
onClick={() => {
|
||||||
|
navigator.clipboard.writeText(data.identity.id);
|
||||||
|
setCopyTextId("Copied");
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<FontAwesomeIcon icon={isCopyingId ? faCheck : faCopy} />
|
||||||
|
</IconButton>
|
||||||
|
</Tooltip>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="mb-4">
|
<div className="mb-4">
|
||||||
<p className="text-sm font-semibold text-mineshaft-300">Name</p>
|
<p className="text-sm font-semibold text-mineshaft-300">Name</p>
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import {
|
|||||||
Tooltip
|
Tooltip
|
||||||
} from "@app/components/v2";
|
} from "@app/components/v2";
|
||||||
import { useTimedReset } from "@app/hooks";
|
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";
|
import { UsePopUpState } from "@app/hooks/usePopUp";
|
||||||
|
|
||||||
const schema = z
|
const schema = z
|
||||||
@@ -34,7 +34,7 @@ type Props = {
|
|||||||
|
|
||||||
export const IdentityTokenModal = ({ popUp, handlePopUpToggle }: Props) => {
|
export const IdentityTokenModal = ({ popUp, handlePopUpToggle }: Props) => {
|
||||||
const { mutateAsync: createToken } = useCreateTokenIdentityTokenAuth();
|
const { mutateAsync: createToken } = useCreateTokenIdentityTokenAuth();
|
||||||
const { mutateAsync: updateToken } = useUpdateTokenIdentityTokenAuth();
|
const { mutateAsync: updateToken } = useUpdateIdentityTokenAuthToken();
|
||||||
const [token, setToken] = useState("");
|
const [token, setToken] = useState("");
|
||||||
const [copyTextToken, isCopyingToken, setCopyTextToken] = useTimedReset<string>({
|
const [copyTextToken, isCopyingToken, setCopyTextToken] = useTimedReset<string>({
|
||||||
initialState: "Copy to clipboard"
|
initialState: "Copy to clipboard"
|
||||||
|
|||||||
+107
-6
@@ -3,15 +3,24 @@ import { Controller, useForm } from "react-hook-form";
|
|||||||
import { yupResolver } from "@hookform/resolvers/yup";
|
import { yupResolver } from "@hookform/resolvers/yup";
|
||||||
import * as yup from "yup";
|
import * as yup from "yup";
|
||||||
|
|
||||||
|
import { createNotification } from "@app/components/notifications";
|
||||||
import {
|
import {
|
||||||
|
DeleteActionModal,
|
||||||
FormControl,
|
FormControl,
|
||||||
Modal,
|
Modal,
|
||||||
ModalContent,
|
ModalContent,
|
||||||
Select,
|
Select,
|
||||||
SelectItem,
|
SelectItem,
|
||||||
UpgradePlanModal
|
UpgradePlanModal} from "@app/components/v2";
|
||||||
} from "@app/components/v2";
|
import { useOrganization } from "@app/context";
|
||||||
import { IdentityAuthMethod } from "@app/hooks/api/identities";
|
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 { UsePopUpState } from "@app/hooks/usePopUp";
|
||||||
|
|
||||||
import { IdentityAwsAuthForm } from "./IdentityAwsAuthForm";
|
import { IdentityAwsAuthForm } from "./IdentityAwsAuthForm";
|
||||||
@@ -22,10 +31,10 @@ import { IdentityTokenAuthForm } from "./IdentityTokenAuthForm";
|
|||||||
import { IdentityUniversalAuthForm } from "./IdentityUniversalAuthForm";
|
import { IdentityUniversalAuthForm } from "./IdentityUniversalAuthForm";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
popUp: UsePopUpState<["identityAuthMethod", "upgradePlan"]>;
|
popUp: UsePopUpState<["identityAuthMethod", "upgradePlan", "revokeAuthMethod"]>;
|
||||||
handlePopUpOpen: (popUpName: keyof UsePopUpState<["upgradePlan"]>) => void;
|
handlePopUpOpen: (popUpName: keyof UsePopUpState<["upgradePlan"]>) => void;
|
||||||
handlePopUpToggle: (
|
handlePopUpToggle: (
|
||||||
popUpName: keyof UsePopUpState<["identityAuthMethod", "upgradePlan"]>,
|
popUpName: keyof UsePopUpState<["identityAuthMethod", "upgradePlan", "revokeAuthMethod"]>,
|
||||||
state?: boolean
|
state?: boolean
|
||||||
) => void;
|
) => void;
|
||||||
};
|
};
|
||||||
@@ -48,6 +57,16 @@ const schema = yup
|
|||||||
export type FormData = yup.InferType<typeof schema>;
|
export type FormData = yup.InferType<typeof schema>;
|
||||||
|
|
||||||
export const IdentityAuthMethodModal = ({ popUp, handlePopUpOpen, handlePopUpToggle }: Props) => {
|
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<FormData>({
|
const { control, watch, setValue } = useForm<FormData>({
|
||||||
resolver: yupResolver(schema),
|
resolver: yupResolver(schema),
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
@@ -128,13 +147,84 @@ export const IdentityAuthMethodModal = ({ popUp, handlePopUpOpen, handlePopUpTog
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
return <div />;
|
return <div />;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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 (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
isOpen={popUp?.identityAuthMethod?.isOpen}
|
isOpen={popUp?.identityAuthMethod?.isOpen}
|
||||||
@@ -175,6 +265,17 @@ export const IdentityAuthMethodModal = ({ popUp, handlePopUpOpen, handlePopUpTog
|
|||||||
onOpenChange={(isOpen) => handlePopUpToggle("upgradePlan", isOpen)}
|
onOpenChange={(isOpen) => handlePopUpToggle("upgradePlan", isOpen)}
|
||||||
text="You can use IP allowlisting if you switch to Infisical's Pro plan."
|
text="You can use IP allowlisting if you switch to Infisical's Pro plan."
|
||||||
/>
|
/>
|
||||||
|
<DeleteActionModal
|
||||||
|
isOpen={popUp?.revokeAuthMethod?.isOpen}
|
||||||
|
title={`Are you sure want to remove ${
|
||||||
|
identityAuthMethodData?.authMethod
|
||||||
|
? identityAuthToNameMap[identityAuthMethodData.authMethod]
|
||||||
|
: "the auth method"
|
||||||
|
} on ${identityAuthMethodData?.name ?? ""}?`}
|
||||||
|
onChange={(isOpen) => handlePopUpToggle("revokeAuthMethod", isOpen)}
|
||||||
|
deleteKey="confirm"
|
||||||
|
onDeleteApproved={onRevokeAuthMethodSubmit}
|
||||||
|
/>
|
||||||
</ModalContent>
|
</ModalContent>
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
|
|||||||
+5
-13
@@ -10,9 +10,9 @@ import { Button, FormControl, IconButton, Input } from "@app/components/v2";
|
|||||||
import { useOrganization, useSubscription } from "@app/context";
|
import { useOrganization, useSubscription } from "@app/context";
|
||||||
import {
|
import {
|
||||||
useAddIdentityAwsAuth,
|
useAddIdentityAwsAuth,
|
||||||
useDeleteIdentityAwsAuth,
|
|
||||||
useGetIdentityAwsAuth,
|
useGetIdentityAwsAuth,
|
||||||
useUpdateIdentityAwsAuth} from "@app/hooks/api";
|
useUpdateIdentityAwsAuth
|
||||||
|
} from "@app/hooks/api";
|
||||||
import { IdentityAuthMethod } from "@app/hooks/api/identities";
|
import { IdentityAuthMethod } from "@app/hooks/api/identities";
|
||||||
import { IdentityTrustedIp } from "@app/hooks/api/identities/types";
|
import { IdentityTrustedIp } from "@app/hooks/api/identities/types";
|
||||||
import { UsePopUpState } from "@app/hooks/usePopUp";
|
import { UsePopUpState } from "@app/hooks/usePopUp";
|
||||||
@@ -42,7 +42,7 @@ export type FormData = yup.InferType<typeof schema>;
|
|||||||
type Props = {
|
type Props = {
|
||||||
handlePopUpOpen: (popUpName: keyof UsePopUpState<["upgradePlan"]>) => void;
|
handlePopUpOpen: (popUpName: keyof UsePopUpState<["upgradePlan"]>) => void;
|
||||||
handlePopUpToggle: (
|
handlePopUpToggle: (
|
||||||
popUpName: keyof UsePopUpState<["identityAuthMethod"]>,
|
popUpName: keyof UsePopUpState<["identityAuthMethod", "revokeAuthMethod"]>,
|
||||||
state?: boolean
|
state?: boolean
|
||||||
) => void;
|
) => void;
|
||||||
identityAuthMethodData: {
|
identityAuthMethodData: {
|
||||||
@@ -63,7 +63,6 @@ export const IdentityAwsAuthForm = ({
|
|||||||
|
|
||||||
const { mutateAsync: addMutateAsync } = useAddIdentityAwsAuth();
|
const { mutateAsync: addMutateAsync } = useAddIdentityAwsAuth();
|
||||||
const { mutateAsync: updateMutateAsync } = useUpdateIdentityAwsAuth();
|
const { mutateAsync: updateMutateAsync } = useUpdateIdentityAwsAuth();
|
||||||
const { mutateAsync: deleteMutateAsync } = useDeleteIdentityAwsAuth();
|
|
||||||
|
|
||||||
const { data } = useGetIdentityAwsAuth(identityAuthMethodData?.identityId ?? "");
|
const { data } = useGetIdentityAwsAuth(identityAuthMethodData?.identityId ?? "");
|
||||||
|
|
||||||
@@ -346,7 +345,7 @@ export const IdentityAwsAuthForm = ({
|
|||||||
variant="plain"
|
variant="plain"
|
||||||
onClick={() => handlePopUpToggle("identityAuthMethod", false)}
|
onClick={() => handlePopUpToggle("identityAuthMethod", false)}
|
||||||
>
|
>
|
||||||
{identityAuthMethodData?.authMethod ? "Cancel" : "Skip"}
|
Cancel
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
{identityAuthMethodData?.authMethod && (
|
{identityAuthMethodData?.authMethod && (
|
||||||
@@ -355,14 +354,7 @@ export const IdentityAwsAuthForm = ({
|
|||||||
colorSchema="danger"
|
colorSchema="danger"
|
||||||
isLoading={isSubmitting}
|
isLoading={isSubmitting}
|
||||||
isDisabled={isSubmitting}
|
isDisabled={isSubmitting}
|
||||||
onClick={async () => {
|
onClick={() => handlePopUpToggle("revokeAuthMethod", true)}
|
||||||
await deleteMutateAsync({
|
|
||||||
identityId: identityAuthMethodData.identityId,
|
|
||||||
organizationId: orgId
|
|
||||||
});
|
|
||||||
|
|
||||||
handlePopUpToggle("identityAuthMethod", false);
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
Remove Auth Method
|
Remove Auth Method
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
+5
-13
@@ -10,9 +10,9 @@ import { Button, FormControl, IconButton, Input } from "@app/components/v2";
|
|||||||
import { useOrganization, useSubscription } from "@app/context";
|
import { useOrganization, useSubscription } from "@app/context";
|
||||||
import {
|
import {
|
||||||
useAddIdentityAzureAuth,
|
useAddIdentityAzureAuth,
|
||||||
useDeleteIdentityAzureAuth,
|
|
||||||
useGetIdentityAzureAuth,
|
useGetIdentityAzureAuth,
|
||||||
useUpdateIdentityAzureAuth} from "@app/hooks/api";
|
useUpdateIdentityAzureAuth
|
||||||
|
} from "@app/hooks/api";
|
||||||
import { IdentityAuthMethod } from "@app/hooks/api/identities";
|
import { IdentityAuthMethod } from "@app/hooks/api/identities";
|
||||||
import { IdentityTrustedIp } from "@app/hooks/api/identities/types";
|
import { IdentityTrustedIp } from "@app/hooks/api/identities/types";
|
||||||
import { UsePopUpState } from "@app/hooks/usePopUp";
|
import { UsePopUpState } from "@app/hooks/usePopUp";
|
||||||
@@ -40,7 +40,7 @@ export type FormData = z.infer<typeof schema>;
|
|||||||
type Props = {
|
type Props = {
|
||||||
handlePopUpOpen: (popUpName: keyof UsePopUpState<["upgradePlan"]>) => void;
|
handlePopUpOpen: (popUpName: keyof UsePopUpState<["upgradePlan"]>) => void;
|
||||||
handlePopUpToggle: (
|
handlePopUpToggle: (
|
||||||
popUpName: keyof UsePopUpState<["identityAuthMethod"]>,
|
popUpName: keyof UsePopUpState<["identityAuthMethod", "revokeAuthMethod"]>,
|
||||||
state?: boolean
|
state?: boolean
|
||||||
) => void;
|
) => void;
|
||||||
identityAuthMethodData: {
|
identityAuthMethodData: {
|
||||||
@@ -61,7 +61,6 @@ export const IdentityAzureAuthForm = ({
|
|||||||
|
|
||||||
const { mutateAsync: addMutateAsync } = useAddIdentityAzureAuth();
|
const { mutateAsync: addMutateAsync } = useAddIdentityAzureAuth();
|
||||||
const { mutateAsync: updateMutateAsync } = useUpdateIdentityAzureAuth();
|
const { mutateAsync: updateMutateAsync } = useUpdateIdentityAzureAuth();
|
||||||
const { mutateAsync: deleteMutateAsync } = useDeleteIdentityAzureAuth();
|
|
||||||
|
|
||||||
const { data } = useGetIdentityAzureAuth(identityAuthMethodData?.identityId ?? "");
|
const { data } = useGetIdentityAzureAuth(identityAuthMethodData?.identityId ?? "");
|
||||||
|
|
||||||
@@ -344,7 +343,7 @@ export const IdentityAzureAuthForm = ({
|
|||||||
variant="plain"
|
variant="plain"
|
||||||
onClick={() => handlePopUpToggle("identityAuthMethod", false)}
|
onClick={() => handlePopUpToggle("identityAuthMethod", false)}
|
||||||
>
|
>
|
||||||
{identityAuthMethodData?.authMethod ? "Cancel" : "Skip"}
|
Cancel
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
{identityAuthMethodData?.authMethod && (
|
{identityAuthMethodData?.authMethod && (
|
||||||
@@ -353,14 +352,7 @@ export const IdentityAzureAuthForm = ({
|
|||||||
colorSchema="danger"
|
colorSchema="danger"
|
||||||
isLoading={isSubmitting}
|
isLoading={isSubmitting}
|
||||||
isDisabled={isSubmitting}
|
isDisabled={isSubmitting}
|
||||||
onClick={async () => {
|
onClick={() => handlePopUpToggle("revokeAuthMethod", true)}
|
||||||
await deleteMutateAsync({
|
|
||||||
identityId: identityAuthMethodData.identityId,
|
|
||||||
organizationId: orgId
|
|
||||||
});
|
|
||||||
|
|
||||||
handlePopUpToggle("identityAuthMethod", false);
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
Remove Auth Method
|
Remove Auth Method
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
+5
-13
@@ -10,9 +10,9 @@ import { Button, FormControl, IconButton, Input, Select, SelectItem } from "@app
|
|||||||
import { useOrganization, useSubscription } from "@app/context";
|
import { useOrganization, useSubscription } from "@app/context";
|
||||||
import {
|
import {
|
||||||
useAddIdentityGcpAuth,
|
useAddIdentityGcpAuth,
|
||||||
useDeleteIdentityGcpAuth,
|
|
||||||
useGetIdentityGcpAuth,
|
useGetIdentityGcpAuth,
|
||||||
useUpdateIdentityGcpAuth} from "@app/hooks/api";
|
useUpdateIdentityGcpAuth
|
||||||
|
} from "@app/hooks/api";
|
||||||
import { IdentityAuthMethod } from "@app/hooks/api/identities";
|
import { IdentityAuthMethod } from "@app/hooks/api/identities";
|
||||||
import { IdentityTrustedIp } from "@app/hooks/api/identities/types";
|
import { IdentityTrustedIp } from "@app/hooks/api/identities/types";
|
||||||
import { UsePopUpState } from "@app/hooks/usePopUp";
|
import { UsePopUpState } from "@app/hooks/usePopUp";
|
||||||
@@ -41,7 +41,7 @@ export type FormData = z.infer<typeof schema>;
|
|||||||
type Props = {
|
type Props = {
|
||||||
handlePopUpOpen: (popUpName: keyof UsePopUpState<["upgradePlan"]>) => void;
|
handlePopUpOpen: (popUpName: keyof UsePopUpState<["upgradePlan"]>) => void;
|
||||||
handlePopUpToggle: (
|
handlePopUpToggle: (
|
||||||
popUpName: keyof UsePopUpState<["identityAuthMethod"]>,
|
popUpName: keyof UsePopUpState<["identityAuthMethod", "revokeAuthMethod"]>,
|
||||||
state?: boolean
|
state?: boolean
|
||||||
) => void;
|
) => void;
|
||||||
identityAuthMethodData: {
|
identityAuthMethodData: {
|
||||||
@@ -62,7 +62,6 @@ export const IdentityGcpAuthForm = ({
|
|||||||
|
|
||||||
const { mutateAsync: addMutateAsync } = useAddIdentityGcpAuth();
|
const { mutateAsync: addMutateAsync } = useAddIdentityGcpAuth();
|
||||||
const { mutateAsync: updateMutateAsync } = useUpdateIdentityGcpAuth();
|
const { mutateAsync: updateMutateAsync } = useUpdateIdentityGcpAuth();
|
||||||
const { mutateAsync: deleteMutateAsync } = useDeleteIdentityGcpAuth();
|
|
||||||
|
|
||||||
const { data } = useGetIdentityGcpAuth(identityAuthMethodData?.identityId ?? "");
|
const { data } = useGetIdentityGcpAuth(identityAuthMethodData?.identityId ?? "");
|
||||||
|
|
||||||
@@ -378,7 +377,7 @@ export const IdentityGcpAuthForm = ({
|
|||||||
variant="plain"
|
variant="plain"
|
||||||
onClick={() => handlePopUpToggle("identityAuthMethod", false)}
|
onClick={() => handlePopUpToggle("identityAuthMethod", false)}
|
||||||
>
|
>
|
||||||
{identityAuthMethodData?.authMethod ? "Cancel" : "Skip"}
|
Cancel
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
{identityAuthMethodData?.authMethod && (
|
{identityAuthMethodData?.authMethod && (
|
||||||
@@ -387,14 +386,7 @@ export const IdentityGcpAuthForm = ({
|
|||||||
colorSchema="danger"
|
colorSchema="danger"
|
||||||
isLoading={isSubmitting}
|
isLoading={isSubmitting}
|
||||||
isDisabled={isSubmitting}
|
isDisabled={isSubmitting}
|
||||||
onClick={async () => {
|
onClick={() => handlePopUpToggle("revokeAuthMethod", true)}
|
||||||
await deleteMutateAsync({
|
|
||||||
identityId: identityAuthMethodData.identityId,
|
|
||||||
organizationId: orgId
|
|
||||||
});
|
|
||||||
|
|
||||||
handlePopUpToggle("identityAuthMethod", false);
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
Remove Auth Method
|
Remove Auth Method
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
+5
-13
@@ -10,9 +10,9 @@ import { Button, FormControl, IconButton, Input, TextArea } from "@app/component
|
|||||||
import { useOrganization, useSubscription } from "@app/context";
|
import { useOrganization, useSubscription } from "@app/context";
|
||||||
import {
|
import {
|
||||||
useAddIdentityKubernetesAuth,
|
useAddIdentityKubernetesAuth,
|
||||||
useDeleteIdentityKubernetesAuth,
|
|
||||||
useGetIdentityKubernetesAuth,
|
useGetIdentityKubernetesAuth,
|
||||||
useUpdateIdentityKubernetesAuth} from "@app/hooks/api";
|
useUpdateIdentityKubernetesAuth
|
||||||
|
} from "@app/hooks/api";
|
||||||
import { IdentityAuthMethod } from "@app/hooks/api/identities";
|
import { IdentityAuthMethod } from "@app/hooks/api/identities";
|
||||||
import { IdentityTrustedIp } from "@app/hooks/api/identities/types";
|
import { IdentityTrustedIp } from "@app/hooks/api/identities/types";
|
||||||
import { UsePopUpState } from "@app/hooks/usePopUp";
|
import { UsePopUpState } from "@app/hooks/usePopUp";
|
||||||
@@ -43,7 +43,7 @@ export type FormData = z.infer<typeof schema>;
|
|||||||
type Props = {
|
type Props = {
|
||||||
handlePopUpOpen: (popUpName: keyof UsePopUpState<["upgradePlan"]>) => void;
|
handlePopUpOpen: (popUpName: keyof UsePopUpState<["upgradePlan"]>) => void;
|
||||||
handlePopUpToggle: (
|
handlePopUpToggle: (
|
||||||
popUpName: keyof UsePopUpState<["identityAuthMethod"]>,
|
popUpName: keyof UsePopUpState<["identityAuthMethod", "revokeAuthMethod"]>,
|
||||||
state?: boolean
|
state?: boolean
|
||||||
) => void;
|
) => void;
|
||||||
identityAuthMethodData: {
|
identityAuthMethodData: {
|
||||||
@@ -64,7 +64,6 @@ export const IdentityKubernetesAuthForm = ({
|
|||||||
|
|
||||||
const { mutateAsync: addMutateAsync } = useAddIdentityKubernetesAuth();
|
const { mutateAsync: addMutateAsync } = useAddIdentityKubernetesAuth();
|
||||||
const { mutateAsync: updateMutateAsync } = useUpdateIdentityKubernetesAuth();
|
const { mutateAsync: updateMutateAsync } = useUpdateIdentityKubernetesAuth();
|
||||||
const { mutateAsync: deleteMutateAsync } = useDeleteIdentityKubernetesAuth();
|
|
||||||
|
|
||||||
const { data } = useGetIdentityKubernetesAuth(identityAuthMethodData?.identityId ?? "");
|
const { data } = useGetIdentityKubernetesAuth(identityAuthMethodData?.identityId ?? "");
|
||||||
|
|
||||||
@@ -399,7 +398,7 @@ export const IdentityKubernetesAuthForm = ({
|
|||||||
variant="plain"
|
variant="plain"
|
||||||
onClick={() => handlePopUpToggle("identityAuthMethod", false)}
|
onClick={() => handlePopUpToggle("identityAuthMethod", false)}
|
||||||
>
|
>
|
||||||
{identityAuthMethodData?.authMethod ? "Cancel" : "Skip"}
|
Cancel
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
{identityAuthMethodData?.authMethod && (
|
{identityAuthMethodData?.authMethod && (
|
||||||
@@ -408,14 +407,7 @@ export const IdentityKubernetesAuthForm = ({
|
|||||||
colorSchema="danger"
|
colorSchema="danger"
|
||||||
isLoading={isSubmitting}
|
isLoading={isSubmitting}
|
||||||
isDisabled={isSubmitting}
|
isDisabled={isSubmitting}
|
||||||
onClick={async () => {
|
onClick={() => handlePopUpToggle("revokeAuthMethod", true)}
|
||||||
await deleteMutateAsync({
|
|
||||||
identityId: identityAuthMethodData.identityId,
|
|
||||||
organizationId: orgId
|
|
||||||
});
|
|
||||||
|
|
||||||
handlePopUpToggle("identityAuthMethod", false);
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
Remove Auth Method
|
Remove Auth Method
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
+3
-3
@@ -15,7 +15,7 @@ import { withPermission } from "@app/hoc";
|
|||||||
import { useDeleteIdentity } from "@app/hooks/api";
|
import { useDeleteIdentity } from "@app/hooks/api";
|
||||||
import { usePopUp } from "@app/hooks/usePopUp";
|
import { usePopUp } from "@app/hooks/usePopUp";
|
||||||
|
|
||||||
import { IdentityAuthMethodModal } from "./IdentityAuthMethodModal";
|
// import { IdentityAuthMethodModal } from "./IdentityAuthMethodModal";
|
||||||
import { IdentityModal } from "./IdentityModal";
|
import { IdentityModal } from "./IdentityModal";
|
||||||
import { IdentityTable } from "./IdentityTable";
|
import { IdentityTable } from "./IdentityTable";
|
||||||
import { IdentityTokenAuthTokenModal } from "./IdentityTokenAuthTokenModal";
|
import { IdentityTokenAuthTokenModal } from "./IdentityTokenAuthTokenModal";
|
||||||
@@ -110,11 +110,11 @@ export const IdentitySection = withPermission(
|
|||||||
</div>
|
</div>
|
||||||
<IdentityTable />
|
<IdentityTable />
|
||||||
<IdentityModal popUp={popUp} handlePopUpToggle={handlePopUpToggle} />
|
<IdentityModal popUp={popUp} handlePopUpToggle={handlePopUpToggle} />
|
||||||
<IdentityAuthMethodModal
|
{/* <IdentityAuthMethodModal
|
||||||
popUp={popUp}
|
popUp={popUp}
|
||||||
handlePopUpOpen={handlePopUpOpen}
|
handlePopUpOpen={handlePopUpOpen}
|
||||||
handlePopUpToggle={handlePopUpToggle}
|
handlePopUpToggle={handlePopUpToggle}
|
||||||
/>
|
/> */}
|
||||||
{/* <IdentityUniversalAuthClientSecretModal
|
{/* <IdentityUniversalAuthClientSecretModal
|
||||||
popUp={popUp}
|
popUp={popUp}
|
||||||
handlePopUpOpen={handlePopUpOpen}
|
handlePopUpOpen={handlePopUpOpen}
|
||||||
|
|||||||
+6
-4
@@ -69,11 +69,13 @@ export const IdentityTable = () => {
|
|||||||
<TBody>
|
<TBody>
|
||||||
{isLoading && <TableSkeleton columns={4} innerKey="org-identities" />}
|
{isLoading && <TableSkeleton columns={4} innerKey="org-identities" />}
|
||||||
{!isLoading &&
|
{!isLoading &&
|
||||||
data &&
|
data?.map(({ identity: { id, name }, role, customRole }) => {
|
||||||
data.length > 0 &&
|
|
||||||
data.map(({ identity: { id, name }, role, customRole }) => {
|
|
||||||
return (
|
return (
|
||||||
<Tr className="h-10" key={`identity-${id}`}>
|
<Tr
|
||||||
|
className="h-10 cursor-pointer transition-colors duration-300 hover:bg-mineshaft-700"
|
||||||
|
key={`identity-${id}`}
|
||||||
|
onClick={() => router.push(`/org/${orgId}/identities/${id}`)}
|
||||||
|
>
|
||||||
<Td>
|
<Td>
|
||||||
<Link href={`/org/${orgId}/identities/${id}`}>{name}</Link>
|
<Link href={`/org/${orgId}/identities/${id}`}>{name}</Link>
|
||||||
</Td>
|
</Td>
|
||||||
|
|||||||
+5
-13
@@ -9,9 +9,9 @@ import { Button, FormControl, IconButton, Input } from "@app/components/v2";
|
|||||||
import { useOrganization, useSubscription } from "@app/context";
|
import { useOrganization, useSubscription } from "@app/context";
|
||||||
import {
|
import {
|
||||||
useAddIdentityTokenAuth,
|
useAddIdentityTokenAuth,
|
||||||
useDeleteIdentityTokenAuth,
|
|
||||||
useGetIdentityTokenAuth,
|
useGetIdentityTokenAuth,
|
||||||
useUpdateIdentityTokenAuth} from "@app/hooks/api";
|
useUpdateIdentityTokenAuth
|
||||||
|
} from "@app/hooks/api";
|
||||||
import { IdentityAuthMethod } from "@app/hooks/api/identities";
|
import { IdentityAuthMethod } from "@app/hooks/api/identities";
|
||||||
import { UsePopUpState } from "@app/hooks/usePopUp";
|
import { UsePopUpState } from "@app/hooks/usePopUp";
|
||||||
|
|
||||||
@@ -35,7 +35,7 @@ export type FormData = z.infer<typeof schema>;
|
|||||||
type Props = {
|
type Props = {
|
||||||
handlePopUpOpen: (popUpName: keyof UsePopUpState<["upgradePlan"]>) => void;
|
handlePopUpOpen: (popUpName: keyof UsePopUpState<["upgradePlan"]>) => void;
|
||||||
handlePopUpToggle: (
|
handlePopUpToggle: (
|
||||||
popUpName: keyof UsePopUpState<["identityAuthMethod"]>,
|
popUpName: keyof UsePopUpState<["identityAuthMethod", "revokeAuthMethod"]>,
|
||||||
state?: boolean
|
state?: boolean
|
||||||
) => void;
|
) => void;
|
||||||
identityAuthMethodData: {
|
identityAuthMethodData: {
|
||||||
@@ -56,7 +56,6 @@ export const IdentityTokenAuthForm = ({
|
|||||||
|
|
||||||
const { mutateAsync: addMutateAsync } = useAddIdentityTokenAuth();
|
const { mutateAsync: addMutateAsync } = useAddIdentityTokenAuth();
|
||||||
const { mutateAsync: updateMutateAsync } = useUpdateIdentityTokenAuth();
|
const { mutateAsync: updateMutateAsync } = useUpdateIdentityTokenAuth();
|
||||||
const { mutateAsync: deleteMutateAsync } = useDeleteIdentityTokenAuth();
|
|
||||||
|
|
||||||
const { data } = useGetIdentityTokenAuth(identityAuthMethodData?.identityId ?? "");
|
const { data } = useGetIdentityTokenAuth(identityAuthMethodData?.identityId ?? "");
|
||||||
|
|
||||||
@@ -256,7 +255,7 @@ export const IdentityTokenAuthForm = ({
|
|||||||
variant="plain"
|
variant="plain"
|
||||||
onClick={() => handlePopUpToggle("identityAuthMethod", false)}
|
onClick={() => handlePopUpToggle("identityAuthMethod", false)}
|
||||||
>
|
>
|
||||||
{identityAuthMethodData?.authMethod ? "Cancel" : "Skip"}
|
Cancel
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
{identityAuthMethodData?.authMethod && (
|
{identityAuthMethodData?.authMethod && (
|
||||||
@@ -265,14 +264,7 @@ export const IdentityTokenAuthForm = ({
|
|||||||
colorSchema="danger"
|
colorSchema="danger"
|
||||||
isLoading={isSubmitting}
|
isLoading={isSubmitting}
|
||||||
isDisabled={isSubmitting}
|
isDisabled={isSubmitting}
|
||||||
onClick={async () => {
|
onClick={() => handlePopUpToggle("revokeAuthMethod", true)}
|
||||||
await deleteMutateAsync({
|
|
||||||
identityId: identityAuthMethodData.identityId,
|
|
||||||
organizationId: orgId
|
|
||||||
});
|
|
||||||
|
|
||||||
handlePopUpToggle("identityAuthMethod", false);
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
Remove Auth Method
|
Remove Auth Method
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
+5
-13
@@ -10,9 +10,9 @@ import { Button, FormControl, IconButton, Input } from "@app/components/v2";
|
|||||||
import { useOrganization, useSubscription } from "@app/context";
|
import { useOrganization, useSubscription } from "@app/context";
|
||||||
import {
|
import {
|
||||||
useAddIdentityUniversalAuth,
|
useAddIdentityUniversalAuth,
|
||||||
useDeleteIdentityUniversalAuth,
|
|
||||||
useGetIdentityUniversalAuth,
|
useGetIdentityUniversalAuth,
|
||||||
useUpdateIdentityUniversalAuth} from "@app/hooks/api";
|
useUpdateIdentityUniversalAuth
|
||||||
|
} from "@app/hooks/api";
|
||||||
import { IdentityAuthMethod } from "@app/hooks/api/identities";
|
import { IdentityAuthMethod } from "@app/hooks/api/identities";
|
||||||
import { IdentityTrustedIp } from "@app/hooks/api/identities/types";
|
import { IdentityTrustedIp } from "@app/hooks/api/identities/types";
|
||||||
import { UsePopUpState } from "@app/hooks/usePopUp";
|
import { UsePopUpState } from "@app/hooks/usePopUp";
|
||||||
@@ -48,7 +48,7 @@ export type FormData = yup.InferType<typeof schema>;
|
|||||||
type Props = {
|
type Props = {
|
||||||
handlePopUpOpen: (popUpName: keyof UsePopUpState<["upgradePlan"]>) => void;
|
handlePopUpOpen: (popUpName: keyof UsePopUpState<["upgradePlan"]>) => void;
|
||||||
handlePopUpToggle: (
|
handlePopUpToggle: (
|
||||||
popUpName: keyof UsePopUpState<["identityAuthMethod"]>,
|
popUpName: keyof UsePopUpState<["identityAuthMethod", "revokeAuthMethod"]>,
|
||||||
state?: boolean
|
state?: boolean
|
||||||
) => void;
|
) => void;
|
||||||
identityAuthMethodData: {
|
identityAuthMethodData: {
|
||||||
@@ -68,7 +68,6 @@ export const IdentityUniversalAuthForm = ({
|
|||||||
const { subscription } = useSubscription();
|
const { subscription } = useSubscription();
|
||||||
const { mutateAsync: addMutateAsync } = useAddIdentityUniversalAuth();
|
const { mutateAsync: addMutateAsync } = useAddIdentityUniversalAuth();
|
||||||
const { mutateAsync: updateMutateAsync } = useUpdateIdentityUniversalAuth();
|
const { mutateAsync: updateMutateAsync } = useUpdateIdentityUniversalAuth();
|
||||||
const { mutateAsync: deleteMutateAsync } = useDeleteIdentityUniversalAuth();
|
|
||||||
const { data } = useGetIdentityUniversalAuth(identityAuthMethodData?.identityId ?? "");
|
const { data } = useGetIdentityUniversalAuth(identityAuthMethodData?.identityId ?? "");
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@@ -385,7 +384,7 @@ export const IdentityUniversalAuthForm = ({
|
|||||||
variant="plain"
|
variant="plain"
|
||||||
onClick={() => handlePopUpToggle("identityAuthMethod", false)}
|
onClick={() => handlePopUpToggle("identityAuthMethod", false)}
|
||||||
>
|
>
|
||||||
{identityAuthMethodData?.authMethod ? "Cancel" : "Skip"}
|
Cancel
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
{identityAuthMethodData?.authMethod && (
|
{identityAuthMethodData?.authMethod && (
|
||||||
@@ -394,14 +393,7 @@ export const IdentityUniversalAuthForm = ({
|
|||||||
colorSchema="danger"
|
colorSchema="danger"
|
||||||
isLoading={isSubmitting}
|
isLoading={isSubmitting}
|
||||||
isDisabled={isSubmitting}
|
isDisabled={isSubmitting}
|
||||||
onClick={async () => {
|
onClick={() => handlePopUpToggle("revokeAuthMethod", true)}
|
||||||
await deleteMutateAsync({
|
|
||||||
identityId: identityAuthMethodData.identityId,
|
|
||||||
organizationId: orgId
|
|
||||||
});
|
|
||||||
|
|
||||||
handlePopUpToggle("identityAuthMethod", false);
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
Remove Auth Method
|
Remove Auth Method
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
Reference in New Issue
Block a user