photoncloud-monorepo/lightningstor/crates/lightningstor-server/src/tenant.rs

59 lines
1.9 KiB
Rust

use tonic::{metadata::MetadataMap, Status};
#[derive(Debug, Clone)]
pub struct TenantContext {
pub org_id: String,
pub project_id: String,
}
fn metadata_value(metadata: &MetadataMap, key: &str) -> Option<String> {
metadata
.get(key)
.and_then(|value| value.to_str().ok())
.map(|value| value.trim().to_string())
.filter(|value| !value.is_empty())
}
fn org_from_metadata(metadata: &MetadataMap) -> Option<String> {
metadata_value(metadata, "org-id")
.or_else(|| metadata_value(metadata, "x-org-id"))
.or_else(|| metadata_value(metadata, "org_id"))
}
fn project_from_metadata(metadata: &MetadataMap) -> Option<String> {
metadata_value(metadata, "project-id")
.or_else(|| metadata_value(metadata, "x-project-id"))
.or_else(|| metadata_value(metadata, "project_id"))
}
pub fn resolve_org(
metadata: &MetadataMap,
org_id: Option<String>,
) -> Result<String, Status> {
org_id
.filter(|value| !value.is_empty())
.or_else(|| org_from_metadata(metadata))
.ok_or_else(|| Status::invalid_argument("org_id is required"))
}
pub fn resolve_org_project_optional(
metadata: &MetadataMap,
org_id: Option<String>,
project_id: Option<String>,
) -> Result<(String, Option<String>), Status> {
let org_id = resolve_org(metadata, org_id)?;
let project_id = project_id
.filter(|value| !value.is_empty())
.or_else(|| project_from_metadata(metadata));
Ok((org_id, project_id))
}
pub fn resolve_tenant(
metadata: &MetadataMap,
org_id: Option<String>,
project_id: Option<String>,
) -> Result<TenantContext, Status> {
let (org_id, project_id) = resolve_org_project_optional(metadata, org_id, project_id)?;
let project_id = project_id.ok_or_else(|| Status::invalid_argument("project_id is required"))?;
Ok(TenantContext { org_id, project_id })
}