mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-08 18:28:12 +00:00
Merge branch 'main' into ENG-2929
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
import { Knex } from "knex";
|
||||
|
||||
import { TableName } from "../schemas";
|
||||
|
||||
export async function up(knex: Knex): Promise<void> {
|
||||
const hasCol = await knex.schema.hasColumn(TableName.Identity, "hasDeleteProtection");
|
||||
if (!hasCol) {
|
||||
await knex.schema.alterTable(TableName.Identity, (t) => {
|
||||
t.boolean("hasDeleteProtection").notNullable().defaultTo(false);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export async function down(knex: Knex): Promise<void> {
|
||||
const hasCol = await knex.schema.hasColumn(TableName.Identity, "hasDeleteProtection");
|
||||
if (hasCol) {
|
||||
await knex.schema.alterTable(TableName.Identity, (t) => {
|
||||
t.dropColumn("hasDeleteProtection");
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,8 @@ export const IdentitiesSchema = z.object({
|
||||
name: z.string(),
|
||||
authMethod: z.string().nullable().optional(),
|
||||
createdAt: z.date(),
|
||||
updatedAt: z.date()
|
||||
updatedAt: z.date(),
|
||||
hasDeleteProtection: z.boolean().default(false)
|
||||
});
|
||||
|
||||
export type TIdentities = z.infer<typeof IdentitiesSchema>;
|
||||
|
||||
@@ -48,7 +48,9 @@ export const registerGroupRouter = async (server: FastifyZodProvider) => {
|
||||
id: z.string().trim().describe(GROUPS.GET_BY_ID.id)
|
||||
}),
|
||||
response: {
|
||||
200: GroupsSchema
|
||||
200: GroupsSchema.extend({
|
||||
customRoleSlug: z.string().nullable()
|
||||
})
|
||||
}
|
||||
},
|
||||
handler: async (req) => {
|
||||
|
||||
@@ -780,6 +780,7 @@ interface CreateIdentityEvent {
|
||||
metadata: {
|
||||
identityId: string;
|
||||
name: string;
|
||||
hasDeleteProtection: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -788,6 +789,7 @@ interface UpdateIdentityEvent {
|
||||
metadata: {
|
||||
identityId: string;
|
||||
name?: string;
|
||||
hasDeleteProtection?: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -169,11 +169,29 @@ export const groupDALFactory = (db: TDbClient) => {
|
||||
}
|
||||
};
|
||||
|
||||
const findById = async (id: string, tx?: Knex) => {
|
||||
try {
|
||||
const doc = await (tx || db.replicaNode())(TableName.Groups)
|
||||
.leftJoin(TableName.OrgRoles, `${TableName.Groups}.roleId`, `${TableName.OrgRoles}.id`)
|
||||
.where(`${TableName.Groups}.id`, id)
|
||||
.select(
|
||||
selectAllTableCols(TableName.Groups),
|
||||
db.ref("slug").as("customRoleSlug").withSchema(TableName.OrgRoles)
|
||||
)
|
||||
.first();
|
||||
|
||||
return doc;
|
||||
} catch (error) {
|
||||
throw new DatabaseError({ error, name: "Find by id" });
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
...groupOrm,
|
||||
findGroups,
|
||||
findByOrgId,
|
||||
findAllGroupPossibleMembers,
|
||||
findGroupsByProjectId,
|
||||
...groupOrm
|
||||
findById
|
||||
};
|
||||
};
|
||||
|
||||
@@ -111,12 +111,14 @@ export const IDENTITIES = {
|
||||
CREATE: {
|
||||
name: "The name of the identity to create.",
|
||||
organizationId: "The organization ID to which the identity belongs.",
|
||||
role: "The role of the identity. Possible values are 'no-access', 'member', and 'admin'."
|
||||
role: "The role of the identity. Possible values are 'no-access', 'member', and 'admin'.",
|
||||
hasDeleteProtection: "Prevents deletion of the identity when enabled."
|
||||
},
|
||||
UPDATE: {
|
||||
identityId: "The ID of the identity to update.",
|
||||
name: "The new name of the identity.",
|
||||
role: "The new role of the identity."
|
||||
role: "The new role of the identity.",
|
||||
hasDeleteProtection: "Prevents deletion of the identity when enabled."
|
||||
},
|
||||
DELETE: {
|
||||
identityId: "The ID of the identity to delete."
|
||||
|
||||
@@ -262,8 +262,8 @@ const envSchema = z
|
||||
DATADOG_HOSTNAME: zpStr(z.string().optional()),
|
||||
|
||||
// PIT
|
||||
PIT_CHECKPOINT_WINDOW: zpStr(z.string().optional().default("2")),
|
||||
PIT_TREE_CHECKPOINT_WINDOW: zpStr(z.string().optional().default("30")),
|
||||
PIT_CHECKPOINT_WINDOW: zpStr(z.string().optional().default("100")),
|
||||
PIT_TREE_CHECKPOINT_WINDOW: zpStr(z.string().optional().default("200")),
|
||||
|
||||
/* CORS ----------------------------------------------------------------------------- */
|
||||
CORS_ALLOWED_ORIGINS: zpStr(
|
||||
|
||||
@@ -44,6 +44,7 @@ export const registerIdentityRouter = async (server: FastifyZodProvider) => {
|
||||
name: z.string().trim().describe(IDENTITIES.CREATE.name),
|
||||
organizationId: z.string().trim().describe(IDENTITIES.CREATE.organizationId),
|
||||
role: z.string().trim().min(1).default(OrgMembershipRole.NoAccess).describe(IDENTITIES.CREATE.role),
|
||||
hasDeleteProtection: z.boolean().default(false).describe(IDENTITIES.CREATE.hasDeleteProtection),
|
||||
metadata: z
|
||||
.object({ key: z.string().trim().min(1), value: z.string().trim().min(1) })
|
||||
.array()
|
||||
@@ -75,6 +76,7 @@ export const registerIdentityRouter = async (server: FastifyZodProvider) => {
|
||||
type: EventType.CREATE_IDENTITY,
|
||||
metadata: {
|
||||
name: identity.name,
|
||||
hasDeleteProtection: identity.hasDeleteProtection,
|
||||
identityId: identity.id
|
||||
}
|
||||
}
|
||||
@@ -86,6 +88,7 @@ export const registerIdentityRouter = async (server: FastifyZodProvider) => {
|
||||
properties: {
|
||||
orgId: req.body.organizationId,
|
||||
name: identity.name,
|
||||
hasDeleteProtection: identity.hasDeleteProtection,
|
||||
identityId: identity.id,
|
||||
...req.auditLogInfo
|
||||
}
|
||||
@@ -117,6 +120,7 @@ export const registerIdentityRouter = async (server: FastifyZodProvider) => {
|
||||
body: z.object({
|
||||
name: z.string().trim().optional().describe(IDENTITIES.UPDATE.name),
|
||||
role: z.string().trim().min(1).optional().describe(IDENTITIES.UPDATE.role),
|
||||
hasDeleteProtection: z.boolean().optional().describe(IDENTITIES.UPDATE.hasDeleteProtection),
|
||||
metadata: z
|
||||
.object({ key: z.string().trim().min(1), value: z.string().trim().min(1) })
|
||||
.array()
|
||||
@@ -148,6 +152,7 @@ export const registerIdentityRouter = async (server: FastifyZodProvider) => {
|
||||
type: EventType.UPDATE_IDENTITY,
|
||||
metadata: {
|
||||
name: identity.name,
|
||||
hasDeleteProtection: identity.hasDeleteProtection,
|
||||
identityId: identity.id
|
||||
}
|
||||
}
|
||||
@@ -243,7 +248,7 @@ export const registerIdentityRouter = async (server: FastifyZodProvider) => {
|
||||
permissions: true,
|
||||
description: true
|
||||
}).optional(),
|
||||
identity: IdentitiesSchema.pick({ name: true, id: true }).extend({
|
||||
identity: IdentitiesSchema.pick({ name: true, id: true, hasDeleteProtection: true }).extend({
|
||||
authMethods: z.array(z.string())
|
||||
})
|
||||
})
|
||||
@@ -292,7 +297,7 @@ export const registerIdentityRouter = async (server: FastifyZodProvider) => {
|
||||
permissions: true,
|
||||
description: true
|
||||
}).optional(),
|
||||
identity: IdentitiesSchema.pick({ name: true, id: true }).extend({
|
||||
identity: IdentitiesSchema.pick({ name: true, id: true, hasDeleteProtection: true }).extend({
|
||||
authMethods: z.array(z.string())
|
||||
})
|
||||
}).array(),
|
||||
@@ -386,7 +391,7 @@ export const registerIdentityRouter = async (server: FastifyZodProvider) => {
|
||||
permissions: true,
|
||||
description: true
|
||||
}).optional(),
|
||||
identity: IdentitiesSchema.pick({ name: true, id: true }).extend({
|
||||
identity: IdentitiesSchema.pick({ name: true, id: true, hasDeleteProtection: true }).extend({
|
||||
authMethods: z.array(z.string())
|
||||
})
|
||||
}).array(),
|
||||
@@ -451,7 +456,7 @@ export const registerIdentityRouter = async (server: FastifyZodProvider) => {
|
||||
temporaryAccessEndTime: z.date().nullable().optional()
|
||||
})
|
||||
),
|
||||
identity: IdentitiesSchema.pick({ name: true, id: true }).extend({
|
||||
identity: IdentitiesSchema.pick({ name: true, id: true, hasDeleteProtection: true }).extend({
|
||||
authMethods: z.array(z.string())
|
||||
}),
|
||||
project: SanitizedProjectSchema.pick({ name: true, id: true, type: true })
|
||||
|
||||
@@ -101,6 +101,7 @@ export const identityProjectDALFactory = (db: TDbClient) => {
|
||||
|
||||
db.ref("id").as("identityId").withSchema(TableName.Identity),
|
||||
db.ref("name").as("identityName").withSchema(TableName.Identity),
|
||||
db.ref("hasDeleteProtection").withSchema(TableName.Identity),
|
||||
db.ref("id").withSchema(TableName.IdentityProjectMembership),
|
||||
db.ref("role").withSchema(TableName.IdentityProjectMembershipRole),
|
||||
db.ref("id").withSchema(TableName.IdentityProjectMembershipRole).as("membershipRoleId"),
|
||||
@@ -130,6 +131,7 @@ export const identityProjectDALFactory = (db: TDbClient) => {
|
||||
data: docs,
|
||||
parentMapper: ({
|
||||
identityName,
|
||||
hasDeleteProtection,
|
||||
uaId,
|
||||
awsId,
|
||||
gcpId,
|
||||
@@ -151,6 +153,7 @@ export const identityProjectDALFactory = (db: TDbClient) => {
|
||||
identity: {
|
||||
id: identityId,
|
||||
name: identityName,
|
||||
hasDeleteProtection,
|
||||
authMethods: buildAuthMethods({
|
||||
uaId,
|
||||
awsId,
|
||||
|
||||
@@ -114,16 +114,18 @@ export const identityOrgDALFactory = (db: TDbClient) => {
|
||||
db.ref("id").as("tokenId").withSchema(TableName.IdentityTokenAuth),
|
||||
db.ref("id").as("jwtId").withSchema(TableName.IdentityJwtAuth),
|
||||
db.ref("id").as("ldapId").withSchema(TableName.IdentityLdapAuth),
|
||||
db.ref("name").withSchema(TableName.Identity)
|
||||
db.ref("name").withSchema(TableName.Identity),
|
||||
db.ref("hasDeleteProtection").withSchema(TableName.Identity)
|
||||
);
|
||||
|
||||
if (data) {
|
||||
const { name } = data;
|
||||
const { name, hasDeleteProtection } = data;
|
||||
return {
|
||||
...data,
|
||||
identity: {
|
||||
id: data.identityId,
|
||||
name,
|
||||
hasDeleteProtection,
|
||||
authMethods: buildAuthMethods(data)
|
||||
}
|
||||
};
|
||||
@@ -155,7 +157,8 @@ export const identityOrgDALFactory = (db: TDbClient) => {
|
||||
.orderBy(`${TableName.Identity}.${orderBy}`, orderDirection)
|
||||
.select(
|
||||
selectAllTableCols(TableName.IdentityOrgMembership),
|
||||
db.ref("name").withSchema(TableName.Identity).as("identityName")
|
||||
db.ref("name").withSchema(TableName.Identity).as("identityName"),
|
||||
db.ref("hasDeleteProtection").withSchema(TableName.Identity)
|
||||
)
|
||||
.where(filter)
|
||||
.as("paginatedIdentity");
|
||||
@@ -245,6 +248,7 @@ export const identityOrgDALFactory = (db: TDbClient) => {
|
||||
db.ref("updatedAt").withSchema("paginatedIdentity"),
|
||||
db.ref("identityId").withSchema("paginatedIdentity").as("identityId"),
|
||||
db.ref("identityName").withSchema("paginatedIdentity"),
|
||||
db.ref("hasDeleteProtection").withSchema("paginatedIdentity"),
|
||||
|
||||
db.ref("id").as("uaId").withSchema(TableName.IdentityUniversalAuth),
|
||||
db.ref("id").as("gcpId").withSchema(TableName.IdentityGcpAuth),
|
||||
@@ -286,6 +290,7 @@ export const identityOrgDALFactory = (db: TDbClient) => {
|
||||
crName,
|
||||
identityId,
|
||||
identityName,
|
||||
hasDeleteProtection,
|
||||
role,
|
||||
roleId,
|
||||
id,
|
||||
@@ -324,6 +329,7 @@ export const identityOrgDALFactory = (db: TDbClient) => {
|
||||
identity: {
|
||||
id: identityId,
|
||||
name: identityName,
|
||||
hasDeleteProtection,
|
||||
authMethods: buildAuthMethods({
|
||||
uaId,
|
||||
alicloudId,
|
||||
@@ -476,6 +482,7 @@ export const identityOrgDALFactory = (db: TDbClient) => {
|
||||
db.ref("updatedAt").withSchema(TableName.IdentityOrgMembership),
|
||||
db.ref("identityId").withSchema(TableName.IdentityOrgMembership).as("identityId"),
|
||||
db.ref("name").withSchema(TableName.Identity).as("identityName"),
|
||||
db.ref("hasDeleteProtection").withSchema(TableName.Identity),
|
||||
|
||||
db.ref("id").as("uaId").withSchema(TableName.IdentityUniversalAuth),
|
||||
db.ref("id").as("gcpId").withSchema(TableName.IdentityGcpAuth),
|
||||
@@ -518,6 +525,7 @@ export const identityOrgDALFactory = (db: TDbClient) => {
|
||||
crName,
|
||||
identityId,
|
||||
identityName,
|
||||
hasDeleteProtection,
|
||||
role,
|
||||
roleId,
|
||||
total_count,
|
||||
@@ -556,6 +564,7 @@ export const identityOrgDALFactory = (db: TDbClient) => {
|
||||
identity: {
|
||||
id: identityId,
|
||||
name: identityName,
|
||||
hasDeleteProtection,
|
||||
authMethods: buildAuthMethods({
|
||||
uaId,
|
||||
alicloudId,
|
||||
|
||||
@@ -47,6 +47,7 @@ export const identityServiceFactory = ({
|
||||
const createIdentity = async ({
|
||||
name,
|
||||
role,
|
||||
hasDeleteProtection,
|
||||
actor,
|
||||
orgId,
|
||||
actorId,
|
||||
@@ -96,7 +97,7 @@ export const identityServiceFactory = ({
|
||||
}
|
||||
|
||||
const identity = await identityDAL.transaction(async (tx) => {
|
||||
const newIdentity = await identityDAL.create({ name }, tx);
|
||||
const newIdentity = await identityDAL.create({ name, hasDeleteProtection }, tx);
|
||||
await identityOrgMembershipDAL.create(
|
||||
{
|
||||
identityId: newIdentity.id,
|
||||
@@ -138,6 +139,7 @@ export const identityServiceFactory = ({
|
||||
const updateIdentity = async ({
|
||||
id,
|
||||
role,
|
||||
hasDeleteProtection,
|
||||
name,
|
||||
actor,
|
||||
actorId,
|
||||
@@ -189,7 +191,11 @@ export const identityServiceFactory = ({
|
||||
}
|
||||
|
||||
const identity = await identityDAL.transaction(async (tx) => {
|
||||
const newIdentity = name ? await identityDAL.updateById(id, { name }, tx) : await identityDAL.findById(id, tx);
|
||||
const newIdentity =
|
||||
name || hasDeleteProtection
|
||||
? await identityDAL.updateById(id, { name, hasDeleteProtection }, tx)
|
||||
: await identityDAL.findById(id, tx);
|
||||
|
||||
if (role) {
|
||||
await identityOrgMembershipDAL.updateById(
|
||||
identityOrgMembership.id,
|
||||
@@ -272,6 +278,9 @@ export const identityServiceFactory = ({
|
||||
|
||||
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionIdentityActions.Delete, OrgPermissionSubjects.Identity);
|
||||
|
||||
if (identityOrgMembership.identity.hasDeleteProtection)
|
||||
throw new BadRequestError({ message: "Identity has delete protection" });
|
||||
|
||||
const deletedIdentity = await identityDAL.deleteById(id);
|
||||
|
||||
await licenseService.updateSubscriptionOrgMemberCount(identityOrgMembership.orgId);
|
||||
|
||||
@@ -5,12 +5,14 @@ import { OrderByDirection, TOrgPermission } from "@app/lib/types";
|
||||
export type TCreateIdentityDTO = {
|
||||
role: string;
|
||||
name: string;
|
||||
hasDeleteProtection: boolean;
|
||||
metadata?: { key: string; value: string }[];
|
||||
} & TOrgPermission;
|
||||
|
||||
export type TUpdateIdentityDTO = {
|
||||
id: string;
|
||||
role?: string;
|
||||
hasDeleteProtection?: boolean;
|
||||
name?: string;
|
||||
metadata?: { key: string; value: string }[];
|
||||
isActorSuperAdmin?: boolean;
|
||||
|
||||
@@ -81,6 +81,7 @@ export type TMachineIdentityCreatedEvent = {
|
||||
event: PostHogEventTypes.MachineIdentityCreated;
|
||||
properties: {
|
||||
name: string;
|
||||
hasDeleteProtection: boolean;
|
||||
orgId: string;
|
||||
identityId: string;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user