mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-12 05:29:16 +00:00
feat: updated settings page
This commit is contained in:
@@ -4,7 +4,7 @@ import { OrganizationsSchema } from "@app/db/schemas";
|
||||
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
|
||||
import { ApiDocsTags, SUB_ORGANIZATIONS } from "@app/lib/api-docs";
|
||||
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||
import { GenericResourceNameSchema } from "@app/server/lib/schemas";
|
||||
import { slugSchema } from "@app/server/lib/schemas";
|
||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||
import { AuthMode } from "@app/services/auth/auth-type";
|
||||
|
||||
@@ -33,7 +33,7 @@ export const registerSubOrgRouter = async (server: FastifyZodProvider) => {
|
||||
}
|
||||
],
|
||||
body: z.object({
|
||||
name: GenericResourceNameSchema.describe(SUB_ORGANIZATIONS.CREATE.name)
|
||||
name: slugSchema().describe(SUB_ORGANIZATIONS.CREATE.name)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
@@ -108,4 +108,55 @@ export const registerSubOrgRouter = async (server: FastifyZodProvider) => {
|
||||
return { organizations };
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
method: "PATCH",
|
||||
url: "/:subOrgId",
|
||||
config: {
|
||||
rateLimit: writeLimit
|
||||
},
|
||||
schema: {
|
||||
hide: false,
|
||||
tags: [ApiDocsTags.SubOrganizations],
|
||||
description: "Update a sub organization",
|
||||
security: [
|
||||
{
|
||||
bearerAuth: []
|
||||
}
|
||||
],
|
||||
params: z.object({
|
||||
subOrgId: z.string().trim().describe(SUB_ORGANIZATIONS.UPDATE.subOrgId)
|
||||
}),
|
||||
body: z.object({
|
||||
name: slugSchema().describe(SUB_ORGANIZATIONS.UPDATE.name)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
organization: sanitizedSubOrganizationSchema
|
||||
})
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT]),
|
||||
handler: async (req) => {
|
||||
const { organization } = await server.services.subOrganization.updateSubOrg({
|
||||
subOrgId: req.params.subOrgId,
|
||||
name: req.body.name,
|
||||
permissionActor: req.permission
|
||||
});
|
||||
|
||||
await server.services.auditLog.createAuditLog({
|
||||
...req.auditLogInfo,
|
||||
orgId: req.permission.orgId,
|
||||
event: {
|
||||
type: EventType.UPDATE_SUB_ORGANIZATION,
|
||||
metadata: {
|
||||
name: req.body.name,
|
||||
organizationId: organization.id
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return { organization };
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@@ -173,7 +173,8 @@ export enum EventType {
|
||||
UPDATE_TOKEN_IDENTITY_TOKEN_AUTH = "update-token-identity-token-auth",
|
||||
GET_TOKENS_IDENTITY_TOKEN_AUTH = "get-tokens-identity-token-auth",
|
||||
|
||||
CREATE_SUB_ORGANIZATION = "create-child-organization",
|
||||
CREATE_SUB_ORGANIZATION = "create-sub-organization",
|
||||
UPDATE_SUB_ORGANIZATION = "update-sub-organization",
|
||||
|
||||
ADD_IDENTITY_TOKEN_AUTH = "add-identity-token-auth",
|
||||
UPDATE_IDENTITY_TOKEN_AUTH = "update-identity-token-auth",
|
||||
@@ -617,6 +618,14 @@ interface CreateSubOrganizationEvent {
|
||||
};
|
||||
}
|
||||
|
||||
interface UpdateSubOrganizationEvent {
|
||||
type: EventType.UPDATE_SUB_ORGANIZATION;
|
||||
metadata: {
|
||||
name: string;
|
||||
organizationId: string;
|
||||
};
|
||||
}
|
||||
|
||||
type TSecretMetadata = { key: string; value: string }[];
|
||||
|
||||
interface GetSecretEvent {
|
||||
@@ -3874,6 +3883,7 @@ interface PamResourceDeleteEvent {
|
||||
|
||||
export type Event =
|
||||
| CreateSubOrganizationEvent
|
||||
| UpdateSubOrganizationEvent
|
||||
| GetSecretsEvent
|
||||
| GetSecretEvent
|
||||
| CreateSecretEvent
|
||||
|
||||
@@ -8,12 +8,19 @@ import { TMembershipRoleDALFactory } from "@app/services/membership/membership-r
|
||||
import { TOrgDALFactory } from "@app/services/org/org-dal";
|
||||
|
||||
import { TLicenseServiceFactory } from "../license/license-service";
|
||||
import { OrgPermissionChildOrgActions, OrgPermissionSubjects } from "../permission/org-permission";
|
||||
import {
|
||||
OrgPermissionActions,
|
||||
OrgPermissionChildOrgActions,
|
||||
OrgPermissionSubjects
|
||||
} from "../permission/org-permission";
|
||||
import { TPermissionServiceFactory } from "../permission/permission-service-types";
|
||||
import { TCreateSubOrgDTO, TListSubOrgDTO } from "./sub-org-types";
|
||||
import { TCreateSubOrgDTO, TListSubOrgDTO, TUpdateSubOrgDTO } from "./sub-org-types";
|
||||
|
||||
type TSubOrgServiceFactoryDep = {
|
||||
orgDAL: Pick<TOrgDALFactory, "findOne" | "create" | "transaction" | "listSubOrganizations">;
|
||||
orgDAL: Pick<
|
||||
TOrgDALFactory,
|
||||
"findOne" | "create" | "transaction" | "listSubOrganizations" | "updateById" | "findById"
|
||||
>;
|
||||
permissionService: Pick<TPermissionServiceFactory, "getOrgPermission">;
|
||||
licenseService: Pick<TLicenseServiceFactory, "getPlan">;
|
||||
membershipDAL: Pick<TMembershipDALFactory, "create">;
|
||||
@@ -113,8 +120,45 @@ export const subOrgServiceFactory = ({
|
||||
};
|
||||
};
|
||||
|
||||
const updateSubOrg = async ({ subOrgId, name, permissionActor }: TUpdateSubOrgDTO) => {
|
||||
const subOrg = await orgDAL.findOne({
|
||||
rootOrgId: permissionActor.rootOrgId,
|
||||
id: subOrgId
|
||||
});
|
||||
if (!subOrg) {
|
||||
throw new BadRequestError({ message: "Sub-organization not found" });
|
||||
}
|
||||
|
||||
const { permission } = await permissionService.getOrgPermission({
|
||||
actorId: permissionActor.id,
|
||||
actor: permissionActor.type,
|
||||
orgId: subOrgId,
|
||||
actorOrgId: subOrgId,
|
||||
actorAuthMethod: permissionActor.authMethod,
|
||||
scope: OrganizationActionScope.ChildOrganization
|
||||
});
|
||||
|
||||
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.Settings);
|
||||
|
||||
const existingSubOrg = await orgDAL.findOne({
|
||||
parentOrgId: subOrg.parentOrgId,
|
||||
slug: name
|
||||
});
|
||||
|
||||
if (existingSubOrg && existingSubOrg.id !== subOrgId) {
|
||||
throw new BadRequestError({ message: `Sub-organization with name ${name} already exists` });
|
||||
}
|
||||
|
||||
const organization = await orgDAL.updateById(subOrgId, { name, slug: name });
|
||||
|
||||
return {
|
||||
organization
|
||||
};
|
||||
};
|
||||
|
||||
return {
|
||||
createSubOrg,
|
||||
listSubOrgs
|
||||
listSubOrgs,
|
||||
updateSubOrg
|
||||
};
|
||||
};
|
||||
|
||||
@@ -14,3 +14,9 @@ export type TListSubOrgDTO = {
|
||||
isAccessible?: boolean;
|
||||
}>;
|
||||
};
|
||||
|
||||
export type TUpdateSubOrgDTO = {
|
||||
subOrgId: string;
|
||||
name: string;
|
||||
permissionActor: OrgServiceActor;
|
||||
};
|
||||
|
||||
@@ -721,6 +721,10 @@ export const SUB_ORGANIZATIONS = {
|
||||
CREATE: {
|
||||
name: "The name of the sub organization to create."
|
||||
},
|
||||
UPDATE: {
|
||||
name: "The name of the sub organization to update.",
|
||||
subOrgId: "The id of the sub organization to update."
|
||||
},
|
||||
LIST: {
|
||||
limit: "The number of sub organizations to return.",
|
||||
offset: "The offset to start from. If you enter 10, it will start from the 10th sub organization.",
|
||||
|
||||
@@ -8,7 +8,7 @@ import { TScimTokenJwtPayload } from "@app/ee/services/scim/scim-types";
|
||||
import { getConfig } from "@app/lib/config/env";
|
||||
import { crypto } from "@app/lib/crypto";
|
||||
import { BadRequestError } from "@app/lib/errors";
|
||||
import { GenericResourceNameSchema } from "@app/server/lib/schemas";
|
||||
import { slugSchema } from "@app/server/lib/schemas";
|
||||
import { ActorType, AuthMethod, AuthMode, AuthModeJwtTokenPayload, AuthTokenType } from "@app/services/auth/auth-type";
|
||||
import { TIdentityAccessTokenJwtPayload } from "@app/services/identity-access-token/identity-access-token-types";
|
||||
import { getServerCfg } from "@app/services/super-admin/super-admin-service";
|
||||
@@ -149,7 +149,7 @@ export const injectIdentity = fp(
|
||||
|
||||
const subOrganizationSelector = req.headers?.["x-infisical-org"] as string | undefined;
|
||||
if (subOrganizationSelector) {
|
||||
await GenericResourceNameSchema.parseAsync(subOrganizationSelector);
|
||||
await slugSchema().parseAsync(subOrganizationSelector);
|
||||
}
|
||||
|
||||
switch (authMode) {
|
||||
|
||||
@@ -31,5 +31,5 @@ export * from "./SecretScanningSecretsDetectedTemplate";
|
||||
export * from "./SecretSyncFailedTemplate";
|
||||
export * from "./ServiceTokenExpiryNoticeTemplate";
|
||||
export * from "./SignupEmailVerificationTemplate";
|
||||
export * from "./UnlockAccountTemplate";
|
||||
export * from "./SubOrganizationInvitationTemplate";
|
||||
export * from "./UnlockAccountTemplate";
|
||||
|
||||
@@ -40,8 +40,8 @@ import {
|
||||
SecretSyncFailedTemplate,
|
||||
ServiceTokenExpiryNoticeTemplate,
|
||||
SignupEmailVerificationTemplate,
|
||||
UnlockAccountTemplate,
|
||||
SubOrganizationInvitationTemplate
|
||||
SubOrganizationInvitationTemplate,
|
||||
UnlockAccountTemplate
|
||||
} from "./emails";
|
||||
|
||||
export type TSmtpConfig = SMTPTransport.Options;
|
||||
|
||||
Reference in New Issue
Block a user