mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-07 15:27:46 +00:00
Merge pull request #2223 from Infisical/misc/add-org-level-rate-limit
misc: moved to license-plan-based rate limits
This commit is contained in:
Vendored
+2
@@ -18,6 +18,7 @@ import { TOidcConfigServiceFactory } from "@app/ee/services/oidc/oidc-config-ser
|
|||||||
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
|
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
|
||||||
import { TProjectUserAdditionalPrivilegeServiceFactory } from "@app/ee/services/project-user-additional-privilege/project-user-additional-privilege-service";
|
import { TProjectUserAdditionalPrivilegeServiceFactory } from "@app/ee/services/project-user-additional-privilege/project-user-additional-privilege-service";
|
||||||
import { TRateLimitServiceFactory } from "@app/ee/services/rate-limit/rate-limit-service";
|
import { TRateLimitServiceFactory } from "@app/ee/services/rate-limit/rate-limit-service";
|
||||||
|
import { RateLimitConfiguration } from "@app/ee/services/rate-limit/rate-limit-types";
|
||||||
import { TSamlConfigServiceFactory } from "@app/ee/services/saml-config/saml-config-service";
|
import { TSamlConfigServiceFactory } from "@app/ee/services/saml-config/saml-config-service";
|
||||||
import { TScimServiceFactory } from "@app/ee/services/scim/scim-service";
|
import { TScimServiceFactory } from "@app/ee/services/scim/scim-service";
|
||||||
import { TSecretApprovalPolicyServiceFactory } from "@app/ee/services/secret-approval-policy/secret-approval-policy-service";
|
import { TSecretApprovalPolicyServiceFactory } from "@app/ee/services/secret-approval-policy/secret-approval-policy-service";
|
||||||
@@ -89,6 +90,7 @@ declare module "fastify" {
|
|||||||
id: string;
|
id: string;
|
||||||
orgId: string;
|
orgId: string;
|
||||||
};
|
};
|
||||||
|
rateLimits: RateLimitConfiguration;
|
||||||
// passport data
|
// passport data
|
||||||
passportUser: {
|
passportUser: {
|
||||||
isUserCompleted: string;
|
isUserCompleted: string;
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
import { Knex } from "knex";
|
||||||
|
|
||||||
|
import { TableName } from "../schemas";
|
||||||
|
|
||||||
|
export async function up(knex: Knex): Promise<void> {
|
||||||
|
const hasCreationLimitCol = await knex.schema.hasColumn(TableName.RateLimit, "creationLimit");
|
||||||
|
await knex.schema.alterTable(TableName.RateLimit, (t) => {
|
||||||
|
if (hasCreationLimitCol) {
|
||||||
|
t.dropColumn("creationLimit");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function down(knex: Knex): Promise<void> {
|
||||||
|
const hasCreationLimitCol = await knex.schema.hasColumn(TableName.RateLimit, "creationLimit");
|
||||||
|
await knex.schema.alterTable(TableName.RateLimit, (t) => {
|
||||||
|
if (!hasCreationLimitCol) {
|
||||||
|
t.integer("creationLimit").defaultTo(30).notNullable();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -15,7 +15,6 @@ export const RateLimitSchema = z.object({
|
|||||||
authRateLimit: z.number().default(60),
|
authRateLimit: z.number().default(60),
|
||||||
inviteUserRateLimit: z.number().default(30),
|
inviteUserRateLimit: z.number().default(30),
|
||||||
mfaRateLimit: z.number().default(20),
|
mfaRateLimit: z.number().default(20),
|
||||||
creationLimit: z.number().default(30),
|
|
||||||
publicEndpointLimit: z.number().default(30),
|
publicEndpointLimit: z.number().default(30),
|
||||||
createdAt: z.date(),
|
createdAt: z.date(),
|
||||||
updatedAt: z.date()
|
updatedAt: z.date()
|
||||||
|
|||||||
@@ -58,7 +58,6 @@ export const registerRateLimitRouter = async (server: FastifyZodProvider) => {
|
|||||||
authRateLimit: z.number(),
|
authRateLimit: z.number(),
|
||||||
inviteUserRateLimit: z.number(),
|
inviteUserRateLimit: z.number(),
|
||||||
mfaRateLimit: z.number(),
|
mfaRateLimit: z.number(),
|
||||||
creationLimit: z.number(),
|
|
||||||
publicEndpointLimit: z.number()
|
publicEndpointLimit: z.number()
|
||||||
}),
|
}),
|
||||||
response: {
|
response: {
|
||||||
|
|||||||
@@ -40,7 +40,12 @@ export const getDefaultOnPremFeatures = (): TFeatureSet => ({
|
|||||||
secretRotation: true,
|
secretRotation: true,
|
||||||
caCrl: false,
|
caCrl: false,
|
||||||
instanceUserManagement: false,
|
instanceUserManagement: false,
|
||||||
externalKms: false
|
externalKms: false,
|
||||||
|
rateLimits: {
|
||||||
|
readLimit: 60,
|
||||||
|
writeLimit: 200,
|
||||||
|
secretsLimit: 40
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
export const setupLicenceRequestWithStore = (baseURL: string, refreshUrl: string, licenseKey: string) => {
|
export const setupLicenceRequestWithStore = (baseURL: string, refreshUrl: string, licenseKey: string) => {
|
||||||
|
|||||||
@@ -58,6 +58,11 @@ export type TFeatureSet = {
|
|||||||
caCrl: false;
|
caCrl: false;
|
||||||
instanceUserManagement: false;
|
instanceUserManagement: false;
|
||||||
externalKms: false;
|
externalKms: false;
|
||||||
|
rateLimits: {
|
||||||
|
readLimit: number;
|
||||||
|
writeLimit: number;
|
||||||
|
secretsLimit: number;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export type TOrgPlansTableDTO = {
|
export type TOrgPlansTableDTO = {
|
||||||
|
|||||||
@@ -4,17 +4,16 @@ import { logger } from "@app/lib/logger";
|
|||||||
|
|
||||||
import { TLicenseServiceFactory } from "../license/license-service";
|
import { TLicenseServiceFactory } from "../license/license-service";
|
||||||
import { TRateLimitDALFactory } from "./rate-limit-dal";
|
import { TRateLimitDALFactory } from "./rate-limit-dal";
|
||||||
import { TRateLimit, TRateLimitUpdateDTO } from "./rate-limit-types";
|
import { RateLimitConfiguration, TRateLimit, TRateLimitUpdateDTO } from "./rate-limit-types";
|
||||||
|
|
||||||
let rateLimitMaxConfiguration = {
|
let rateLimitMaxConfiguration: RateLimitConfiguration = {
|
||||||
readLimit: 60,
|
readLimit: 60,
|
||||||
publicEndpointLimit: 30,
|
publicEndpointLimit: 30,
|
||||||
writeLimit: 200,
|
writeLimit: 200,
|
||||||
secretsLimit: 60,
|
secretsLimit: 60,
|
||||||
authRateLimit: 60,
|
authRateLimit: 60,
|
||||||
inviteUserRateLimit: 30,
|
inviteUserRateLimit: 30,
|
||||||
mfaRateLimit: 20,
|
mfaRateLimit: 20
|
||||||
creationLimit: 30
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Object.freeze(rateLimitMaxConfiguration);
|
Object.freeze(rateLimitMaxConfiguration);
|
||||||
@@ -67,8 +66,7 @@ export const rateLimitServiceFactory = ({ rateLimitDAL, licenseService }: TRateL
|
|||||||
secretsLimit: rateLimit.secretsRateLimit,
|
secretsLimit: rateLimit.secretsRateLimit,
|
||||||
authRateLimit: rateLimit.authRateLimit,
|
authRateLimit: rateLimit.authRateLimit,
|
||||||
inviteUserRateLimit: rateLimit.inviteUserRateLimit,
|
inviteUserRateLimit: rateLimit.inviteUserRateLimit,
|
||||||
mfaRateLimit: rateLimit.mfaRateLimit,
|
mfaRateLimit: rateLimit.mfaRateLimit
|
||||||
creationLimit: rateLimit.creationLimit
|
|
||||||
};
|
};
|
||||||
|
|
||||||
logger.info(`syncRateLimitConfiguration: rate limit configuration: %o`, newRateLimitMaxConfiguration);
|
logger.info(`syncRateLimitConfiguration: rate limit configuration: %o`, newRateLimitMaxConfiguration);
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ export type TRateLimitUpdateDTO = {
|
|||||||
authRateLimit: number;
|
authRateLimit: number;
|
||||||
inviteUserRateLimit: number;
|
inviteUserRateLimit: number;
|
||||||
mfaRateLimit: number;
|
mfaRateLimit: number;
|
||||||
creationLimit: number;
|
|
||||||
publicEndpointLimit: number;
|
publicEndpointLimit: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -14,3 +13,13 @@ export type TRateLimit = {
|
|||||||
createdAt: Date;
|
createdAt: Date;
|
||||||
updatedAt: Date;
|
updatedAt: Date;
|
||||||
} & TRateLimitUpdateDTO;
|
} & TRateLimitUpdateDTO;
|
||||||
|
|
||||||
|
export type RateLimitConfiguration = {
|
||||||
|
readLimit: number;
|
||||||
|
publicEndpointLimit: number;
|
||||||
|
writeLimit: number;
|
||||||
|
secretsLimit: number;
|
||||||
|
authRateLimit: number;
|
||||||
|
inviteUserRateLimit: number;
|
||||||
|
mfaRateLimit: number;
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import type { RateLimitOptions, RateLimitPluginOptions } from "@fastify/rate-limit";
|
import type { RateLimitOptions, RateLimitPluginOptions } from "@fastify/rate-limit";
|
||||||
import { Redis } from "ioredis";
|
import { Redis } from "ioredis";
|
||||||
|
|
||||||
import { getRateLimiterConfig } from "@app/ee/services/rate-limit/rate-limit-service";
|
|
||||||
import { getConfig } from "@app/lib/config/env";
|
import { getConfig } from "@app/lib/config/env";
|
||||||
|
|
||||||
export const globalRateLimiterCfg = (): RateLimitPluginOptions => {
|
export const globalRateLimiterCfg = (): RateLimitPluginOptions => {
|
||||||
@@ -22,14 +21,16 @@ export const globalRateLimiterCfg = (): RateLimitPluginOptions => {
|
|||||||
// GET endpoints
|
// GET endpoints
|
||||||
export const readLimit: RateLimitOptions = {
|
export const readLimit: RateLimitOptions = {
|
||||||
timeWindow: 60 * 1000,
|
timeWindow: 60 * 1000,
|
||||||
max: () => getRateLimiterConfig().readLimit,
|
hook: "preValidation",
|
||||||
|
max: (req) => req.rateLimits.readLimit,
|
||||||
keyGenerator: (req) => req.realIp
|
keyGenerator: (req) => req.realIp
|
||||||
};
|
};
|
||||||
|
|
||||||
// POST, PATCH, PUT, DELETE endpoints
|
// POST, PATCH, PUT, DELETE endpoints
|
||||||
export const writeLimit: RateLimitOptions = {
|
export const writeLimit: RateLimitOptions = {
|
||||||
timeWindow: 60 * 1000,
|
timeWindow: 60 * 1000,
|
||||||
max: () => getRateLimiterConfig().writeLimit,
|
hook: "preValidation",
|
||||||
|
max: (req) => req.rateLimits.writeLimit,
|
||||||
keyGenerator: (req) => req.realIp
|
keyGenerator: (req) => req.realIp
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -37,42 +38,40 @@ export const writeLimit: RateLimitOptions = {
|
|||||||
export const secretsLimit: RateLimitOptions = {
|
export const secretsLimit: RateLimitOptions = {
|
||||||
// secrets, folders, secret imports
|
// secrets, folders, secret imports
|
||||||
timeWindow: 60 * 1000,
|
timeWindow: 60 * 1000,
|
||||||
max: () => getRateLimiterConfig().secretsLimit,
|
hook: "preValidation",
|
||||||
|
max: (req) => req.rateLimits.secretsLimit,
|
||||||
keyGenerator: (req) => req.realIp
|
keyGenerator: (req) => req.realIp
|
||||||
};
|
};
|
||||||
|
|
||||||
export const authRateLimit: RateLimitOptions = {
|
export const authRateLimit: RateLimitOptions = {
|
||||||
timeWindow: 60 * 1000,
|
timeWindow: 60 * 1000,
|
||||||
max: () => getRateLimiterConfig().authRateLimit,
|
hook: "preValidation",
|
||||||
|
max: (req) => req.rateLimits.authRateLimit,
|
||||||
keyGenerator: (req) => req.realIp
|
keyGenerator: (req) => req.realIp
|
||||||
};
|
};
|
||||||
|
|
||||||
export const inviteUserRateLimit: RateLimitOptions = {
|
export const inviteUserRateLimit: RateLimitOptions = {
|
||||||
timeWindow: 60 * 1000,
|
timeWindow: 60 * 1000,
|
||||||
max: () => getRateLimiterConfig().inviteUserRateLimit,
|
hook: "preValidation",
|
||||||
|
max: (req) => req.rateLimits.inviteUserRateLimit,
|
||||||
keyGenerator: (req) => req.realIp
|
keyGenerator: (req) => req.realIp
|
||||||
};
|
};
|
||||||
|
|
||||||
export const mfaRateLimit: RateLimitOptions = {
|
export const mfaRateLimit: RateLimitOptions = {
|
||||||
timeWindow: 60 * 1000,
|
timeWindow: 60 * 1000,
|
||||||
max: () => getRateLimiterConfig().mfaRateLimit,
|
hook: "preValidation",
|
||||||
|
max: (req) => req.rateLimits.mfaRateLimit,
|
||||||
keyGenerator: (req) => {
|
keyGenerator: (req) => {
|
||||||
return req.headers.authorization?.split(" ")[1] || req.realIp;
|
return req.headers.authorization?.split(" ")[1] || req.realIp;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const creationLimit: RateLimitOptions = {
|
|
||||||
// identity, project, org
|
|
||||||
timeWindow: 60 * 1000,
|
|
||||||
max: () => getRateLimiterConfig().creationLimit,
|
|
||||||
keyGenerator: (req) => req.realIp
|
|
||||||
};
|
|
||||||
|
|
||||||
// Public endpoints to avoid brute force attacks
|
// Public endpoints to avoid brute force attacks
|
||||||
export const publicEndpointLimit: RateLimitOptions = {
|
export const publicEndpointLimit: RateLimitOptions = {
|
||||||
// Read Shared Secrets
|
// Read Shared Secrets
|
||||||
timeWindow: 60 * 1000,
|
timeWindow: 60 * 1000,
|
||||||
max: () => getRateLimiterConfig().publicEndpointLimit,
|
hook: "preValidation",
|
||||||
|
max: (req) => req.rateLimits.publicEndpointLimit,
|
||||||
keyGenerator: (req) => req.realIp
|
keyGenerator: (req) => req.realIp
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
import fp from "fastify-plugin";
|
||||||
|
|
||||||
|
import { getRateLimiterConfig } from "@app/ee/services/rate-limit/rate-limit-service";
|
||||||
|
import { getConfig } from "@app/lib/config/env";
|
||||||
|
|
||||||
|
export const injectRateLimits = fp(async (server) => {
|
||||||
|
server.decorateRequest("rateLimits", null);
|
||||||
|
server.addHook("onRequest", async (req) => {
|
||||||
|
const appCfg = getConfig();
|
||||||
|
|
||||||
|
const instanceRateLimiterConfig = getRateLimiterConfig();
|
||||||
|
if (!req.auth?.orgId) {
|
||||||
|
// for public endpoints, we always use the instance-wide default rate limits
|
||||||
|
req.rateLimits = instanceRateLimiterConfig;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { rateLimits, customRateLimits } = await server.services.license.getPlan(req.auth.orgId);
|
||||||
|
|
||||||
|
if (customRateLimits && !appCfg.isCloud) {
|
||||||
|
// we do this because for self-hosted/dedicated instances, we want custom rate limits to be based on admin configuration
|
||||||
|
// note that the syncing of custom rate limit happens on the instanceRateLimiterConfig object
|
||||||
|
req.rateLimits = instanceRateLimiterConfig;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// we're using the null coalescing operator in order to handle outdated licenses
|
||||||
|
req.rateLimits = {
|
||||||
|
readLimit: rateLimits?.readLimit ?? instanceRateLimiterConfig.readLimit,
|
||||||
|
writeLimit: rateLimits?.writeLimit ?? instanceRateLimiterConfig.writeLimit,
|
||||||
|
secretsLimit: rateLimits?.secretsLimit ?? instanceRateLimiterConfig.secretsLimit,
|
||||||
|
publicEndpointLimit: instanceRateLimiterConfig.publicEndpointLimit,
|
||||||
|
authRateLimit: instanceRateLimiterConfig.authRateLimit,
|
||||||
|
inviteUserRateLimit: instanceRateLimiterConfig.inviteUserRateLimit,
|
||||||
|
mfaRateLimit: instanceRateLimiterConfig.mfaRateLimit
|
||||||
|
};
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -184,6 +184,7 @@ import { webhookServiceFactory } from "@app/services/webhook/webhook-service";
|
|||||||
import { injectAuditLogInfo } from "../plugins/audit-log";
|
import { injectAuditLogInfo } from "../plugins/audit-log";
|
||||||
import { injectIdentity } from "../plugins/auth/inject-identity";
|
import { injectIdentity } from "../plugins/auth/inject-identity";
|
||||||
import { injectPermission } from "../plugins/auth/inject-permission";
|
import { injectPermission } from "../plugins/auth/inject-permission";
|
||||||
|
import { injectRateLimits } from "../plugins/inject-rate-limits";
|
||||||
import { registerSecretScannerGhApp } from "../plugins/secret-scanner";
|
import { registerSecretScannerGhApp } from "../plugins/secret-scanner";
|
||||||
import { registerV1Routes } from "./v1";
|
import { registerV1Routes } from "./v1";
|
||||||
import { registerV2Routes } from "./v2";
|
import { registerV2Routes } from "./v2";
|
||||||
@@ -1149,6 +1150,7 @@ export const registerRoutes = async (
|
|||||||
|
|
||||||
await server.register(injectIdentity, { userDAL, serviceTokenDAL });
|
await server.register(injectIdentity, { userDAL, serviceTokenDAL });
|
||||||
await server.register(injectPermission);
|
await server.register(injectPermission);
|
||||||
|
await server.register(injectRateLimits);
|
||||||
await server.register(injectAuditLogInfo);
|
await server.register(injectAuditLogInfo);
|
||||||
|
|
||||||
server.route({
|
server.route({
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { z } from "zod";
|
|||||||
import { IdentitiesSchema, IdentityOrgMembershipsSchema, OrgMembershipRole, OrgRolesSchema } from "@app/db/schemas";
|
import { IdentitiesSchema, IdentityOrgMembershipsSchema, OrgMembershipRole, OrgRolesSchema } from "@app/db/schemas";
|
||||||
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
|
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
|
||||||
import { IDENTITIES } from "@app/lib/api-docs";
|
import { IDENTITIES } from "@app/lib/api-docs";
|
||||||
import { creationLimit, readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||||
import { getTelemetryDistinctId } from "@app/server/lib/telemetry";
|
import { getTelemetryDistinctId } from "@app/server/lib/telemetry";
|
||||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||||
import { AuthMode } from "@app/services/auth/auth-type";
|
import { AuthMode } from "@app/services/auth/auth-type";
|
||||||
@@ -16,7 +16,7 @@ export const registerIdentityRouter = async (server: FastifyZodProvider) => {
|
|||||||
method: "POST",
|
method: "POST",
|
||||||
url: "/",
|
url: "/",
|
||||||
config: {
|
config: {
|
||||||
rateLimit: creationLimit
|
rateLimit: writeLimit
|
||||||
},
|
},
|
||||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||||
schema: {
|
schema: {
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import {
|
|||||||
UsersSchema
|
UsersSchema
|
||||||
} from "@app/db/schemas";
|
} from "@app/db/schemas";
|
||||||
import { ORGANIZATIONS } from "@app/lib/api-docs";
|
import { ORGANIZATIONS } from "@app/lib/api-docs";
|
||||||
import { creationLimit, readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||||
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";
|
||||||
|
|
||||||
@@ -307,7 +307,7 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
|
|||||||
method: "POST",
|
method: "POST",
|
||||||
url: "/",
|
url: "/",
|
||||||
config: {
|
config: {
|
||||||
rateLimit: creationLimit
|
rateLimit: writeLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
body: z.object({
|
body: z.object({
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { z } from "zod";
|
|||||||
import { CertificateAuthoritiesSchema, CertificatesSchema, ProjectKeysSchema } from "@app/db/schemas";
|
import { CertificateAuthoritiesSchema, CertificatesSchema, ProjectKeysSchema } from "@app/db/schemas";
|
||||||
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
|
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
|
||||||
import { PROJECTS } from "@app/lib/api-docs";
|
import { PROJECTS } from "@app/lib/api-docs";
|
||||||
import { creationLimit, readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||||
import { getTelemetryDistinctId } from "@app/server/lib/telemetry";
|
import { getTelemetryDistinctId } from "@app/server/lib/telemetry";
|
||||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||||
import { AuthMode } from "@app/services/auth/auth-type";
|
import { AuthMode } from "@app/services/auth/auth-type";
|
||||||
@@ -142,7 +142,7 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
|
|||||||
method: "POST",
|
method: "POST",
|
||||||
url: "/",
|
url: "/",
|
||||||
config: {
|
config: {
|
||||||
rateLimit: creationLimit
|
rateLimit: writeLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
description: "Create a new project",
|
description: "Create a new project",
|
||||||
|
|||||||
@@ -5,6 +5,5 @@ export type TRateLimit = {
|
|||||||
authRateLimit: number;
|
authRateLimit: number;
|
||||||
inviteUserRateLimit: number;
|
inviteUserRateLimit: number;
|
||||||
mfaRateLimit: number;
|
mfaRateLimit: number;
|
||||||
creationLimit: number;
|
|
||||||
publicEndpointLimit: number;
|
publicEndpointLimit: number;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ const formSchema = z.object({
|
|||||||
authRateLimit: z.number(),
|
authRateLimit: z.number(),
|
||||||
inviteUserRateLimit: z.number(),
|
inviteUserRateLimit: z.number(),
|
||||||
mfaRateLimit: z.number(),
|
mfaRateLimit: z.number(),
|
||||||
creationLimit: z.number(),
|
|
||||||
publicEndpointLimit: z.number()
|
publicEndpointLimit: z.number()
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -41,7 +40,6 @@ export const RateLimitPanel = () => {
|
|||||||
authRateLimit: rateLimit?.authRateLimit ?? 60,
|
authRateLimit: rateLimit?.authRateLimit ?? 60,
|
||||||
inviteUserRateLimit: rateLimit?.inviteUserRateLimit ?? 30,
|
inviteUserRateLimit: rateLimit?.inviteUserRateLimit ?? 30,
|
||||||
mfaRateLimit: rateLimit?.mfaRateLimit ?? 20,
|
mfaRateLimit: rateLimit?.mfaRateLimit ?? 20,
|
||||||
creationLimit: rateLimit?.creationLimit ?? 30,
|
|
||||||
publicEndpointLimit: rateLimit?.publicEndpointLimit ?? 30
|
publicEndpointLimit: rateLimit?.publicEndpointLimit ?? 30
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -60,7 +58,6 @@ export const RateLimitPanel = () => {
|
|||||||
authRateLimit,
|
authRateLimit,
|
||||||
inviteUserRateLimit,
|
inviteUserRateLimit,
|
||||||
mfaRateLimit,
|
mfaRateLimit,
|
||||||
creationLimit,
|
|
||||||
publicEndpointLimit
|
publicEndpointLimit
|
||||||
} = formData;
|
} = formData;
|
||||||
|
|
||||||
@@ -71,7 +68,6 @@ export const RateLimitPanel = () => {
|
|||||||
authRateLimit,
|
authRateLimit,
|
||||||
inviteUserRateLimit,
|
inviteUserRateLimit,
|
||||||
mfaRateLimit,
|
mfaRateLimit,
|
||||||
creationLimit,
|
|
||||||
publicEndpointLimit
|
publicEndpointLimit
|
||||||
});
|
});
|
||||||
createNotification({
|
createNotification({
|
||||||
@@ -210,25 +206,6 @@ export const RateLimitPanel = () => {
|
|||||||
</FormControl>
|
</FormControl>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
<Controller
|
|
||||||
control={control}
|
|
||||||
defaultValue={300}
|
|
||||||
name="creationLimit"
|
|
||||||
render={({ field, fieldState: { error } }) => (
|
|
||||||
<FormControl
|
|
||||||
label="New resource creation requests per minute"
|
|
||||||
className="w-72"
|
|
||||||
isError={Boolean(error)}
|
|
||||||
errorText={error?.message}
|
|
||||||
>
|
|
||||||
<Input
|
|
||||||
{...field}
|
|
||||||
value={field.value || ""}
|
|
||||||
onChange={(e) => field.onChange(Number(e.target.value))}
|
|
||||||
/>
|
|
||||||
</FormControl>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
<Controller
|
<Controller
|
||||||
control={control}
|
control={control}
|
||||||
defaultValue={300}
|
defaultValue={300}
|
||||||
|
|||||||
Reference in New Issue
Block a user