mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-06 22:27:22 +00:00
improvement: add organization name constraint
This commit is contained in:
@@ -21,3 +21,10 @@ export const slugSchema = ({ min = 1, max = 32, field = "Slug" }: SlugSchemaInpu
|
|||||||
message: `${field} field can only contain lowercase letters, numbers, and hyphens`
|
message: `${field} field can only contain lowercase letters, numbers, and hyphens`
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const OrganizationNameSchema = z
|
||||||
|
.string()
|
||||||
|
.trim()
|
||||||
|
.min(1, { message: "Name must be at least 1 character" })
|
||||||
|
.max(64, { message: "Name must be 64 or fewer characters" })
|
||||||
|
.regex(/^[a-zA-Z0-9\-_\s]+$/, "Name can only contain alphanumeric characters, dashes, underscores, and spaces");
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import { EventType, UserAgentType } from "@app/ee/services/audit-log/audit-log-t
|
|||||||
import { AUDIT_LOGS, ORGANIZATIONS } from "@app/lib/api-docs";
|
import { AUDIT_LOGS, ORGANIZATIONS } from "@app/lib/api-docs";
|
||||||
import { getLastMidnightDateISO, removeTrailingSlash } from "@app/lib/fn";
|
import { getLastMidnightDateISO, removeTrailingSlash } from "@app/lib/fn";
|
||||||
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||||
import { slugSchema } from "@app/server/lib/schemas";
|
import { OrganizationNameSchema, slugSchema } from "@app/server/lib/schemas";
|
||||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||||
import { ActorType, AuthMode, MfaMethod } from "@app/services/auth/auth-type";
|
import { ActorType, AuthMode, MfaMethod } from "@app/services/auth/auth-type";
|
||||||
import { sanitizedOrganizationSchema } from "@app/services/org/org-schema";
|
import { sanitizedOrganizationSchema } from "@app/services/org/org-schema";
|
||||||
@@ -251,7 +251,7 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
|
|||||||
schema: {
|
schema: {
|
||||||
params: z.object({ organizationId: z.string().trim() }),
|
params: z.object({ organizationId: z.string().trim() }),
|
||||||
body: z.object({
|
body: z.object({
|
||||||
name: z.string().trim().max(64, { message: "Name must be 64 or fewer characters" }).optional(),
|
name: OrganizationNameSchema.optional(),
|
||||||
slug: slugSchema({ max: 64 }).optional(),
|
slug: slugSchema({ max: 64 }).optional(),
|
||||||
authEnforced: z.boolean().optional(),
|
authEnforced: z.boolean().optional(),
|
||||||
scimEnabled: z.boolean().optional(),
|
scimEnabled: z.boolean().optional(),
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import {
|
|||||||
import { ORGANIZATIONS } from "@app/lib/api-docs";
|
import { ORGANIZATIONS } from "@app/lib/api-docs";
|
||||||
import { getConfig } from "@app/lib/config/env";
|
import { getConfig } from "@app/lib/config/env";
|
||||||
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||||
|
import { OrganizationNameSchema } from "@app/server/lib/schemas";
|
||||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||||
import { ActorType, AuthMode } from "@app/services/auth/auth-type";
|
import { ActorType, AuthMode } from "@app/services/auth/auth-type";
|
||||||
|
|
||||||
@@ -330,7 +331,7 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
|
|||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
body: z.object({
|
body: z.object({
|
||||||
name: z.string().trim()
|
name: OrganizationNameSchema
|
||||||
}),
|
}),
|
||||||
response: {
|
response: {
|
||||||
200: z.object({
|
200: z.object({
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { UsersSchema } from "@app/db/schemas";
|
|||||||
import { getConfig } from "@app/lib/config/env";
|
import { getConfig } from "@app/lib/config/env";
|
||||||
import { ForbiddenRequestError } from "@app/lib/errors";
|
import { ForbiddenRequestError } from "@app/lib/errors";
|
||||||
import { authRateLimit } from "@app/server/config/rateLimiter";
|
import { authRateLimit } from "@app/server/config/rateLimiter";
|
||||||
|
import { OrganizationNameSchema } from "@app/server/lib/schemas";
|
||||||
import { getServerCfg } from "@app/services/super-admin/super-admin-service";
|
import { getServerCfg } from "@app/services/super-admin/super-admin-service";
|
||||||
import { PostHogEventTypes } from "@app/services/telemetry/telemetry-types";
|
import { PostHogEventTypes } from "@app/services/telemetry/telemetry-types";
|
||||||
|
|
||||||
@@ -100,7 +101,7 @@ export const registerSignupRouter = async (server: FastifyZodProvider) => {
|
|||||||
encryptedPrivateKeyTag: z.string().trim(),
|
encryptedPrivateKeyTag: z.string().trim(),
|
||||||
salt: z.string().trim(),
|
salt: z.string().trim(),
|
||||||
verifier: z.string().trim(),
|
verifier: z.string().trim(),
|
||||||
organizationName: z.string().trim().min(1),
|
organizationName: OrganizationNameSchema,
|
||||||
providerAuthToken: z.string().trim().optional().nullish(),
|
providerAuthToken: z.string().trim().optional().nullish(),
|
||||||
attributionSource: z.string().trim().optional(),
|
attributionSource: z.string().trim().optional(),
|
||||||
password: z.string()
|
password: z.string()
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import { encodeBase64 } from "tweetnacl-util";
|
|||||||
import { initProjectHelper } from "@app/helpers/project";
|
import { initProjectHelper } from "@app/helpers/project";
|
||||||
import { completeAccountSignup, useSelectOrganization } from "@app/hooks/api/auth/queries";
|
import { completeAccountSignup, useSelectOrganization } from "@app/hooks/api/auth/queries";
|
||||||
import { fetchOrganizations } from "@app/hooks/api/organization/queries";
|
import { fetchOrganizations } from "@app/hooks/api/organization/queries";
|
||||||
|
import { onRequestError } from "@app/hooks/api/reactQuery";
|
||||||
|
|
||||||
import InputField from "../basic/InputField";
|
import InputField from "../basic/InputField";
|
||||||
import checkPassword from "../utilities/checks/password/checkPassword";
|
import checkPassword from "../utilities/checks/password/checkPassword";
|
||||||
@@ -206,6 +207,7 @@ export default function UserInfoStep({
|
|||||||
|
|
||||||
incrementStep();
|
incrementStep();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
onRequestError(error);
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
console.error(error);
|
console.error(error);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ export const CreateOrgModal: FC<CreateOrgModalProps> = ({ isOpen, onClose }) =>
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal isOpen={isOpen}>
|
<Modal modal={false} isOpen={isOpen}>
|
||||||
<ModalContent
|
<ModalContent
|
||||||
title="Create Organization"
|
title="Create Organization"
|
||||||
subTitle="Looks like you're not part of any organizations. Create one to start using Infisical"
|
subTitle="Looks like you're not part of any organizations. Create one to start using Infisical"
|
||||||
|
|||||||
@@ -22,9 +22,7 @@ const camelCaseToSpaces = (input: string) => {
|
|||||||
return input.replace(/([a-z])([A-Z])/g, "$1 $2");
|
return input.replace(/([a-z])([A-Z])/g, "$1 $2");
|
||||||
};
|
};
|
||||||
|
|
||||||
export const queryClient = new QueryClient({
|
export const onRequestError = (error: unknown) => {
|
||||||
mutationCache: new MutationCache({
|
|
||||||
onError: (error) => {
|
|
||||||
if (axios.isAxiosError(error)) {
|
if (axios.isAxiosError(error)) {
|
||||||
const serverResponse = error.response?.data as TApiErrors;
|
const serverResponse = error.response?.data as TApiErrors;
|
||||||
if (serverResponse?.error === ApiErrorTypes.ValidationError) {
|
if (serverResponse?.error === ApiErrorTypes.ValidationError) {
|
||||||
@@ -121,9 +119,7 @@ export const queryClient = new QueryClient({
|
|||||||
if (typeof operators === "string") {
|
if (typeof operators === "string") {
|
||||||
return (
|
return (
|
||||||
<li
|
<li
|
||||||
key={`Forbidden-error-details-${index + 1}-${
|
key={`Forbidden-error-details-${index + 1}-${fieldIndex + 1}`}
|
||||||
fieldIndex + 1
|
|
||||||
}`}
|
|
||||||
>
|
>
|
||||||
<span className="font-bold capitalize">
|
<span className="font-bold capitalize">
|
||||||
{formattedFieldName}
|
{formattedFieldName}
|
||||||
@@ -140,9 +136,7 @@ export const queryClient = new QueryClient({
|
|||||||
fieldIndex + 1
|
fieldIndex + 1
|
||||||
}-${operatorIndex + 1}`}
|
}-${operatorIndex + 1}`}
|
||||||
>
|
>
|
||||||
<span className="font-bold capitalize">
|
<span className="font-bold capitalize">{formattedFieldName}</span>{" "}
|
||||||
{formattedFieldName}
|
|
||||||
</span>{" "}
|
|
||||||
<span className="text-mineshaft-200">
|
<span className="text-mineshaft-200">
|
||||||
{
|
{
|
||||||
formatedConditionsOperatorNames[
|
formatedConditionsOperatorNames[
|
||||||
@@ -151,9 +145,7 @@ export const queryClient = new QueryClient({
|
|||||||
}
|
}
|
||||||
</span>{" "}
|
</span>{" "}
|
||||||
<span className="text-yellow-600">
|
<span className="text-yellow-600">
|
||||||
{operators[
|
{operators[operator as PermissionConditionOperators].toString()}
|
||||||
operator as PermissionConditionOperators
|
|
||||||
].toString()}
|
|
||||||
</span>
|
</span>
|
||||||
</li>
|
</li>
|
||||||
));
|
));
|
||||||
@@ -192,7 +184,11 @@ export const queryClient = new QueryClient({
|
|||||||
]
|
]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
|
export const queryClient = new QueryClient({
|
||||||
|
mutationCache: new MutationCache({
|
||||||
|
onError: onRequestError
|
||||||
}),
|
}),
|
||||||
defaultOptions: {
|
defaultOptions: {
|
||||||
queries: {
|
queries: {
|
||||||
|
|||||||
Reference in New Issue
Block a user