This commit is contained in:
Nell committed 2026-10-18 18:46:52 +02:00
1 parent 0cb8b068a8
commit 64b0c76120
11 files changed
+453 -5

No files matched your search

+77 -1
View File
@@ -8,7 +8,7 @@ use crate::repositories::{AnyResult, RepositoryContext};
use sea_orm::{
ColumnTrait, EntityTrait, PaginatorTrait, QueryFilter, QuerySelect, Set, TransactionTrait,
};
use std::collections::HashMap;
use std::collections::{HashMap, HashSet};
use std::sync::{Arc, OnceLock};
use uuid::Uuid;
@@ -81,6 +81,39 @@ impl ComputedPermissionRepository {
Ok(())
}
/// Répare les membres sans aucune ligne de cache. Les membres déjà synchronisés ne sont pas recalculés.
pub async fn repair_missing_members(&self) -> AnyResult<Vec<(Uuid, Uuid)>> {
let members = server_user::Entity::find()
.select_only()
.column(server_user::Column::UserId)
.column(server_user::Column::ServerId)
.into_tuple::<(Uuid, Uuid)>()
.all(&self.context.db)
.await?;
let cached: HashSet<(Uuid, Uuid)> = computed_permission::Entity::find()
.select_only()
.column(computed_permission::Column::UserId)
.column(computed_permission::Column::ServerId)
.distinct()
.into_tuple::<(Uuid, Uuid)>()
.all(&self.context.db)
.await?
.into_iter()
.collect();
let mut repaired = Vec::new();
for (user_id, server_id) in members {
if cached.contains(&(user_id, server_id)) {
continue;
}
self.full_sync_user(user_id, server_id).await?;
repaired.push((user_id, server_id));
}
Ok(repaired)
}
/// Scope RÔLE : Recalcule le cache uniquement pour les membres d'un rôle spécifique.
pub async fn sync_role_members(&self, role_id: Uuid, server_id: Uuid) -> AnyResult<()> {
let user_ids = role_user::Entity::find()
@@ -263,3 +296,46 @@ impl ComputedPermissionRepository {
Ok(())
}
}
#[cfg(test)]
mod tests {
use crate::http::test_support::{state, user};
use crate::models::computed_permission;
use sea_orm::{ColumnTrait, EntityTrait, QueryFilter};
#[tokio::test]
async fn repair_missing_members_is_idempotent() {
let state = state().await;
let owner = user(&state, false).await;
let server = state
.services
.server
.create_server("repair".into(), None, false, owner.id)
.await
.unwrap();
computed_permission::Entity::delete_many()
.filter(computed_permission::Column::UserId.eq(owner.id))
.filter(computed_permission::Column::ServerId.eq(server.id))
.exec(&state.db)
.await
.unwrap();
let first = state
.repositories
.computed_permission
.repair_missing_members()
.await
.unwrap();
let second = state
.repositories
.computed_permission
.repair_missing_members()
.await
.unwrap();
assert!(first.contains(&(owner.id, server.id)));
assert!(second.is_empty());
}
}