Check rate limit for a request. Called after identity and blacklist checks, before query execution. Returns `Err(RateLimited)` if the request exceeds the rate limit. Tenant and database QPS caps are read from the quota catalog when available. Check order: user → org → tenant → database.
(
state: &SharedState,
identity: &AuthenticatedIdentity,
auth_ctx: &AuthContext,
operation: &str,
database_id: nodedb_types::DatabaseId,
)
| 103 | /// Tenant and database QPS caps are read from the quota catalog when available. |
| 104 | /// Check order: user → org → tenant → database. |
| 105 | pub fn check_rate_limit( |
| 106 | state: &SharedState, |
| 107 | identity: &AuthenticatedIdentity, |
| 108 | auth_ctx: &AuthContext, |
| 109 | operation: &str, |
| 110 | database_id: nodedb_types::DatabaseId, |
| 111 | ) -> crate::Result<crate::control::security::ratelimit::limiter::RateLimitResult> { |
| 112 | use crate::control::security::ratelimit::limiter::QuotaCheckParams; |
| 113 | |
| 114 | let plan_tier = auth_ctx.metadata.get("plan").map(|s| s.as_str()); |
| 115 | |
| 116 | // Resolve tenant and database QPS caps from the quota catalog if available. |
| 117 | let quota_params = state.credentials.catalog().as_ref().and_then(|catalog| { |
| 118 | let tenant_max_qps = catalog |
| 119 | .get_tenant_quota(database_id, identity.tenant_id) |
| 120 | .ok() |
| 121 | .flatten() |
| 122 | .and_then(|r| { |
| 123 | if r.max_qps > 0 { |
| 124 | Some(r.max_qps as u64) |
| 125 | } else { |
| 126 | None |
| 127 | } |
| 128 | }); |
| 129 | |
| 130 | let database_max_qps = catalog |
| 131 | .get_database_quota(database_id) |
| 132 | .ok() |
| 133 | .flatten() |
| 134 | .and_then(|r| { |
| 135 | if r.max_qps > 0 { |
| 136 | Some(r.max_qps as u64) |
| 137 | } else { |
| 138 | None |
| 139 | } |
| 140 | }); |
| 141 | |
| 142 | if tenant_max_qps.is_some() || database_max_qps.is_some() { |
| 143 | Some(QuotaCheckParams { |
| 144 | tenant_max_qps, |
| 145 | database_max_qps, |
| 146 | tenant_id: identity.tenant_id, |
| 147 | database_id, |
| 148 | }) |
| 149 | } else { |
| 150 | None |
| 151 | } |
| 152 | }); |
| 153 | |
| 154 | let result = state.rate_limiter.check( |
| 155 | &identity.user_id.to_string(), |
| 156 | &auth_ctx.org_ids, |
| 157 | plan_tier, |
| 158 | operation, |
| 159 | quota_params.as_ref(), |
| 160 | ); |
| 161 | |
| 162 | if !result.allowed { |
nothing calls this directly
no test coverage detected