multi tenancy part 1

This commit is contained in:
2025-10-22 22:52:59 +02:00
parent 8e3f09774a
commit e175d28c2c
35 changed files with 1288 additions and 314 deletions
+46 -4
View File
@@ -15,6 +15,8 @@ pub struct JwtService {
expiry: Duration,
download_audience: String,
download_expiry: Duration,
selector_audience: String,
selector_expiry: Duration,
}
impl JwtService {
@@ -27,16 +29,18 @@ impl JwtService {
expiry: Duration::minutes(config.jwt_expiry_minutes),
download_audience: config.download_token_audience.clone(),
download_expiry: Duration::minutes(config.download_token_expiry_minutes),
selector_audience: format!("{}:tenant-selector", config.jwt_audience),
selector_expiry: Duration::minutes(15),
})
}
pub fn generate_token(&self, user_id: Uuid, username: &str, role: &str) -> Result<String> {
pub fn generate_token(&self, user_id: Uuid, tenant_id: Uuid, username: &str) -> Result<String> {
let now = Utc::now();
let exp = now + self.expiry;
let claims = Claims {
sub: user_id,
tenant_id,
username: username.to_owned(),
role: role.to_owned(),
iss: self.issuer.clone(),
aud: self.audience.clone(),
iat: now.timestamp() as usize,
@@ -54,12 +58,18 @@ impl JwtService {
Ok(data.claims)
}
pub fn generate_download_token(&self, document_id: Uuid, user_id: Uuid) -> Result<String> {
pub fn generate_download_token(
&self,
document_id: Uuid,
user_id: Uuid,
tenant_id: Uuid,
) -> Result<String> {
let now = Utc::now();
let exp = now + self.download_expiry;
let claims = DownloadClaims {
doc_id: document_id,
user_id,
tenant_id,
iss: self.issuer.clone(),
aud: self.download_audience.clone(),
iat: now.timestamp() as usize,
@@ -76,13 +86,35 @@ impl JwtService {
let data = decode::<DownloadClaims>(token, &self.decoding, &validation)?;
Ok(data.claims)
}
pub fn generate_tenant_selector_token(&self, user_id: Uuid) -> Result<String> {
let now = Utc::now();
let exp = now + self.selector_expiry;
let claims = TenantSelectionClaims {
sub: user_id,
iss: self.issuer.clone(),
aud: self.selector_audience.clone(),
iat: now.timestamp() as usize,
exp: exp.timestamp() as usize,
};
Ok(encode(&Header::default(), &claims, &self.encoding)?)
}
pub fn verify_tenant_selector_token(&self, token: &str) -> Result<TenantSelectionClaims> {
let mut validation = Validation::default();
validation.set_audience(&[self.selector_audience.clone()]);
validation.set_issuer(&[self.issuer.clone()]);
let data = decode::<TenantSelectionClaims>(token, &self.decoding, &validation)?;
Ok(data.claims)
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Claims {
pub sub: Uuid,
pub tenant_id: Uuid,
pub username: String,
pub role: String,
pub iss: String,
pub aud: String,
pub iat: usize,
@@ -93,6 +125,16 @@ pub struct Claims {
pub struct DownloadClaims {
pub doc_id: Uuid,
pub user_id: Uuid,
pub tenant_id: Uuid,
pub iss: String,
pub aud: String,
pub iat: usize,
pub exp: usize,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TenantSelectionClaims {
pub sub: Uuid,
pub iss: String,
pub aud: String,
pub iat: usize,