Merge branch 'main' into rfc-4331-quota-properties
# Conflicts: # src/interfaces/nextcloud/report_handler.rs # src/interfaces/nextcloud/webdav_handler.rs # tests/api/run.sh
This commit is contained in:
@@ -931,6 +931,50 @@ pub struct FeaturesConfig {
|
||||
///
|
||||
/// Env: `OXICLOUD_WEBDAV_DRIVE_LISTING_PREFIX`.
|
||||
pub webdav_drive_listing_prefix: String,
|
||||
|
||||
/// Background purge of expired `storage.role_grants` rows.
|
||||
///
|
||||
/// The AuthZ engine already filters expired grants out of every
|
||||
/// permission check at read time (`expires_at IS NULL OR
|
||||
/// expires_at > NOW()`), so leaving the rows in place is a
|
||||
/// hygiene issue — not a security one. This purge deletes rows
|
||||
/// whose `expires_at` is more than [`GrantCleanupConfig::grace_days`]
|
||||
/// in the past, preserving the audit / support answer to
|
||||
/// "what happened to my access?" for the grace window.
|
||||
///
|
||||
/// Enabled by default: expired-auth-row cleanup is a
|
||||
/// security-hygiene default, not opt-in.
|
||||
pub grant_cleanup: GrantCleanupConfig,
|
||||
}
|
||||
|
||||
/// Config for the daily expired-grant purge (see
|
||||
/// [`FeaturesConfig::grant_cleanup`]).
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct GrantCleanupConfig {
|
||||
/// Master switch. Env: `OXICLOUD_GRANT_CLEANUP_ENABLED`
|
||||
/// (default `true`).
|
||||
pub enabled: bool,
|
||||
/// Days past a grant's `expires_at` before the row is eligible
|
||||
/// for deletion. Env: `OXICLOUD_GRANT_CLEANUP_GRACE_DAYS`
|
||||
/// (default `15`).
|
||||
///
|
||||
/// The recommendation is `> 15` — enough to answer
|
||||
/// support/audit questions about recently-lapsed grants without
|
||||
/// keeping dead rows forever.
|
||||
pub grace_days: u32,
|
||||
/// How often the daemon fires, in hours. Env:
|
||||
/// `OXICLOUD_GRANT_CLEANUP_INTERVAL_HOURS` (default `24`).
|
||||
pub interval_hours: u64,
|
||||
}
|
||||
|
||||
impl Default for GrantCleanupConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
enabled: true,
|
||||
grace_days: 15,
|
||||
interval_hours: 24,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for FeaturesConfig {
|
||||
@@ -954,6 +998,7 @@ impl Default for FeaturesConfig {
|
||||
// maps to the caller's default drive; drive listing is
|
||||
// reachable at `/webdav/@drive/`.
|
||||
webdav_drive_listing_prefix: "@drive".to_string(),
|
||||
grant_cleanup: GrantCleanupConfig::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1525,6 +1570,25 @@ impl AppConfig {
|
||||
config.features.enable_admin_internal_endpoints = val;
|
||||
}
|
||||
|
||||
// Grant-cleanup daemon. Purges rows from `storage.role_grants`
|
||||
// whose `expires_at` is more than `grace_days` in the past.
|
||||
// See `GrantCleanupConfig` for defaults + rationale.
|
||||
if let Ok(v) = env::var("OXICLOUD_GRANT_CLEANUP_ENABLED").map(|v| v.parse::<bool>())
|
||||
&& let Ok(val) = v
|
||||
{
|
||||
config.features.grant_cleanup.enabled = val;
|
||||
}
|
||||
if let Ok(v) = env::var("OXICLOUD_GRANT_CLEANUP_GRACE_DAYS").map(|v| v.parse::<u32>())
|
||||
&& let Ok(val) = v
|
||||
{
|
||||
config.features.grant_cleanup.grace_days = val;
|
||||
}
|
||||
if let Ok(v) = env::var("OXICLOUD_GRANT_CLEANUP_INTERVAL_HOURS").map(|v| v.parse::<u64>())
|
||||
&& let Ok(val) = v
|
||||
{
|
||||
config.features.grant_cleanup.interval_hours = val.max(1);
|
||||
}
|
||||
|
||||
// Native WebDAV drive-picker path segment. Sanitised by
|
||||
// stripping leading/trailing slashes so operators can pass
|
||||
// `/drives/` or `drives` interchangeably; empty string means
|
||||
|
||||
@@ -1293,6 +1293,9 @@ impl AppServiceFactory {
|
||||
let places_service: Option<Arc<PlacesService>>;
|
||||
let people_service: Option<Arc<PeopleService>>;
|
||||
let storage_usage_service: Option<Arc<StorageUsageService>>;
|
||||
let grant_cleanup_service: Option<
|
||||
Arc<crate::infrastructure::services::grant_cleanup_service::GrantCleanupService>,
|
||||
>;
|
||||
let mut auth_services: Option<crate::common::di::AuthServices> = None;
|
||||
let mut nextcloud_services: Option<NextcloudServices> = None;
|
||||
// Lifted out of the database-services block so PR 9's invite
|
||||
@@ -1336,6 +1339,25 @@ impl AppServiceFactory {
|
||||
|
||||
self.start_content_index_job(&maintenance_pool, &core, content_index);
|
||||
|
||||
grant_cleanup_service = if core.config.features.grant_cleanup.enabled {
|
||||
let svc = Arc::new(
|
||||
crate::infrastructure::services::grant_cleanup_service::GrantCleanupService::new(
|
||||
authorization.clone(),
|
||||
core.config.features.grant_cleanup.grace_days,
|
||||
core.config.features.grant_cleanup.interval_hours,
|
||||
),
|
||||
);
|
||||
// First tick fires immediately inside start_cleanup_job —
|
||||
// matches the trash/storage-usage daemon shape.
|
||||
svc.clone().start_cleanup_job().await;
|
||||
Some(svc)
|
||||
} else {
|
||||
tracing::info!(
|
||||
"Grant-cleanup daemon disabled by OXICLOUD_GRANT_CLEANUP_ENABLED=false"
|
||||
);
|
||||
None
|
||||
};
|
||||
|
||||
// User-lifecycle dispatcher. Hook order is registration order;
|
||||
// document dependencies inline if/when any arise. Today:
|
||||
// 1. AuditLifecycleHook — fires first so the
|
||||
@@ -1560,6 +1582,7 @@ impl AppServiceFactory {
|
||||
places_service,
|
||||
people_service,
|
||||
storage_usage_service,
|
||||
grant_cleanup_service,
|
||||
calendar_service: None,
|
||||
calendar_use_case: None,
|
||||
addressbook_use_case: None,
|
||||
@@ -2032,6 +2055,14 @@ pub struct AppState {
|
||||
pub places_service: Option<Arc<PlacesService>>,
|
||||
pub people_service: Option<Arc<PeopleService>>,
|
||||
pub storage_usage_service: Option<Arc<StorageUsageService>>,
|
||||
/// Handle to the background daemon that purges expired
|
||||
/// `storage.role_grants` rows. `None` when the daemon is disabled
|
||||
/// via `OXICLOUD_GRANT_CLEANUP_ENABLED=false`. The admin
|
||||
/// `POST /api/admin/internal/trigger-grant-cleanup` handler uses
|
||||
/// this to invoke the purge on demand (test-only).
|
||||
pub grant_cleanup_service: Option<
|
||||
Arc<crate::infrastructure::services::grant_cleanup_service::GrantCleanupService>,
|
||||
>,
|
||||
pub calendar_service: Option<Arc<CalendarService>>,
|
||||
pub calendar_use_case: Option<Arc<CalendarService>>,
|
||||
pub addressbook_use_case: Option<Arc<ContactService>>,
|
||||
|
||||
Reference in New Issue
Block a user