fix: critical bugs from deep audit
- Fix copy_files() data loss: implement real copy_file across full stack (FileWritePort, FileManagementUseCase, stubs, service, repository with atomic CTE + dedup ref_count increment, batch_operations caller) - Fix plaintext password in replace_default_admin: hash password via PasswordHasherPort before User::new() - Fix CalendarService hardcoded user_id: unify CalendarUseCase trait with explicit user_id parameter on all methods, remove zombie _for_user duplicates and hardcoded 'current_user_id', update 20 CalDAV handler call sites - Previous session: migrate DedupService to PostgreSQL (storage.blobs), atomic CTEs with compensation for file/folder repository operations
This commit is contained in:
@@ -24,13 +24,8 @@ impl CalendarUseCase for CalendarService {
|
||||
async fn create_calendar(
|
||||
&self,
|
||||
calendar: CreateCalendarDto,
|
||||
user_id: &str,
|
||||
) -> Result<CalendarDto, DomainError> {
|
||||
// This function requires the current user context which will come from middleware
|
||||
// For now, we'll use a dummy implementation that needs to be completed
|
||||
|
||||
// In a real implementation, get user_id from current user context
|
||||
let user_id = "current_user_id"; // This should come from middleware
|
||||
|
||||
self.calendar_storage
|
||||
.create_calendar(calendar, user_id)
|
||||
.await
|
||||
@@ -40,20 +35,12 @@ impl CalendarUseCase for CalendarService {
|
||||
&self,
|
||||
calendar_id: &str,
|
||||
update: UpdateCalendarDto,
|
||||
user_id: &str,
|
||||
) -> Result<CalendarDto, DomainError> {
|
||||
// In a real implementation, we would:
|
||||
// 1. Get the current user ID from middleware
|
||||
// 2. Verify that the user has access to this calendar
|
||||
// 3. Update the calendar if they have permission
|
||||
|
||||
let user_id = "current_user_id"; // This should come from middleware
|
||||
|
||||
// Check if user has access
|
||||
let has_access = self
|
||||
.calendar_storage
|
||||
.check_calendar_access(calendar_id, user_id)
|
||||
.await?;
|
||||
|
||||
if !has_access {
|
||||
return Err(DomainError::new(
|
||||
ErrorKind::AccessDenied,
|
||||
@@ -61,21 +48,16 @@ impl CalendarUseCase for CalendarService {
|
||||
"You don't have permission to update this calendar",
|
||||
));
|
||||
}
|
||||
|
||||
self.calendar_storage
|
||||
.update_calendar(calendar_id, update)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn delete_calendar(&self, calendar_id: &str) -> Result<(), DomainError> {
|
||||
let user_id = "current_user_id"; // This should come from middleware
|
||||
|
||||
// Check if user has access
|
||||
async fn delete_calendar(&self, calendar_id: &str, user_id: &str) -> Result<(), DomainError> {
|
||||
let has_access = self
|
||||
.calendar_storage
|
||||
.check_calendar_access(calendar_id, user_id)
|
||||
.await?;
|
||||
|
||||
if !has_access {
|
||||
return Err(DomainError::new(
|
||||
ErrorKind::AccessDenied,
|
||||
@@ -83,22 +65,19 @@ impl CalendarUseCase for CalendarService {
|
||||
"You don't have permission to delete this calendar",
|
||||
));
|
||||
}
|
||||
|
||||
self.calendar_storage.delete_calendar(calendar_id).await
|
||||
}
|
||||
|
||||
async fn get_calendar(&self, calendar_id: &str) -> Result<CalendarDto, DomainError> {
|
||||
let user_id = "current_user_id"; // This should come from middleware
|
||||
|
||||
// Get the calendar
|
||||
async fn get_calendar(
|
||||
&self,
|
||||
calendar_id: &str,
|
||||
user_id: &str,
|
||||
) -> Result<CalendarDto, DomainError> {
|
||||
let calendar = self.calendar_storage.get_calendar(calendar_id).await?;
|
||||
|
||||
// Check if user has access or if calendar is public
|
||||
let has_access = self
|
||||
.calendar_storage
|
||||
.check_calendar_access(calendar_id, user_id)
|
||||
.await?;
|
||||
|
||||
if !has_access && !calendar.is_public {
|
||||
return Err(DomainError::new(
|
||||
ErrorKind::AccessDenied,
|
||||
@@ -106,19 +85,14 @@ impl CalendarUseCase for CalendarService {
|
||||
"You don't have permission to view this calendar",
|
||||
));
|
||||
}
|
||||
|
||||
Ok(calendar)
|
||||
}
|
||||
|
||||
async fn list_my_calendars(&self) -> Result<Vec<CalendarDto>, DomainError> {
|
||||
let user_id = "current_user_id"; // This should come from middleware
|
||||
|
||||
async fn list_my_calendars(&self, user_id: &str) -> Result<Vec<CalendarDto>, DomainError> {
|
||||
self.calendar_storage.list_calendars_by_owner(user_id).await
|
||||
}
|
||||
|
||||
async fn list_shared_calendars(&self) -> Result<Vec<CalendarDto>, DomainError> {
|
||||
let user_id = "current_user_id"; // This should come from middleware
|
||||
|
||||
async fn list_shared_calendars(&self, user_id: &str) -> Result<Vec<CalendarDto>, DomainError> {
|
||||
self.calendar_storage
|
||||
.list_calendars_shared_with_user(user_id)
|
||||
.await
|
||||
@@ -131,7 +105,6 @@ impl CalendarUseCase for CalendarService {
|
||||
) -> Result<Vec<CalendarDto>, DomainError> {
|
||||
let limit = limit.unwrap_or(100);
|
||||
let offset = offset.unwrap_or(0);
|
||||
|
||||
self.calendar_storage
|
||||
.list_public_calendars(limit, offset)
|
||||
.await
|
||||
@@ -140,24 +113,18 @@ impl CalendarUseCase for CalendarService {
|
||||
async fn share_calendar(
|
||||
&self,
|
||||
calendar_id: &str,
|
||||
user_id: &str,
|
||||
target_user_id: &str,
|
||||
access_level: &str,
|
||||
caller_user_id: &str,
|
||||
) -> Result<(), DomainError> {
|
||||
let current_user_id = "current_user_id"; // This should come from middleware
|
||||
|
||||
// Check if current user has access
|
||||
let calendar = self.calendar_storage.get_calendar(calendar_id).await?;
|
||||
|
||||
// Only the owner can share the calendar
|
||||
if calendar.owner_id != current_user_id {
|
||||
if calendar.owner_id != caller_user_id {
|
||||
return Err(DomainError::new(
|
||||
ErrorKind::AccessDenied,
|
||||
"Calendar",
|
||||
"Only the calendar owner can change sharing settings",
|
||||
));
|
||||
}
|
||||
|
||||
// Validate access_level
|
||||
match access_level {
|
||||
"read" | "write" | "owner" => {}
|
||||
_ => {
|
||||
@@ -171,66 +138,55 @@ impl CalendarUseCase for CalendarService {
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
self.calendar_storage
|
||||
.share_calendar(calendar_id, user_id, access_level)
|
||||
.share_calendar(calendar_id, target_user_id, access_level)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn remove_calendar_sharing(
|
||||
&self,
|
||||
calendar_id: &str,
|
||||
user_id: &str,
|
||||
target_user_id: &str,
|
||||
caller_user_id: &str,
|
||||
) -> Result<(), DomainError> {
|
||||
let current_user_id = "current_user_id"; // This should come from middleware
|
||||
|
||||
// Check if current user has access
|
||||
let calendar = self.calendar_storage.get_calendar(calendar_id).await?;
|
||||
|
||||
// Only the owner can change sharing settings
|
||||
if calendar.owner_id != current_user_id {
|
||||
if calendar.owner_id != caller_user_id {
|
||||
return Err(DomainError::new(
|
||||
ErrorKind::AccessDenied,
|
||||
"Calendar",
|
||||
"Only the calendar owner can change sharing settings",
|
||||
));
|
||||
}
|
||||
|
||||
self.calendar_storage
|
||||
.remove_calendar_sharing(calendar_id, user_id)
|
||||
.remove_calendar_sharing(calendar_id, target_user_id)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn get_calendar_shares(
|
||||
&self,
|
||||
calendar_id: &str,
|
||||
user_id: &str,
|
||||
) -> Result<Vec<(String, String)>, DomainError> {
|
||||
let current_user_id = "current_user_id"; // This should come from middleware
|
||||
|
||||
// Check if current user has access
|
||||
let calendar = self.calendar_storage.get_calendar(calendar_id).await?;
|
||||
|
||||
// Only the owner can view sharing settings
|
||||
if calendar.owner_id != current_user_id {
|
||||
if calendar.owner_id != user_id {
|
||||
return Err(DomainError::new(
|
||||
ErrorKind::AccessDenied,
|
||||
"Calendar",
|
||||
"Only the calendar owner can view sharing settings",
|
||||
));
|
||||
}
|
||||
|
||||
self.calendar_storage.get_calendar_shares(calendar_id).await
|
||||
}
|
||||
|
||||
async fn create_event(&self, event: CreateEventDto) -> Result<CalendarEventDto, DomainError> {
|
||||
let user_id = "current_user_id"; // This should come from middleware
|
||||
|
||||
// Check if user has access to the calendar
|
||||
async fn create_event(
|
||||
&self,
|
||||
event: CreateEventDto,
|
||||
user_id: &str,
|
||||
) -> Result<CalendarEventDto, DomainError> {
|
||||
let has_access = self
|
||||
.calendar_storage
|
||||
.check_calendar_access(&event.calendar_id, user_id)
|
||||
.await?;
|
||||
|
||||
if !has_access {
|
||||
return Err(DomainError::new(
|
||||
ErrorKind::AccessDenied,
|
||||
@@ -238,22 +194,18 @@ impl CalendarUseCase for CalendarService {
|
||||
"You don't have permission to add events to this calendar",
|
||||
));
|
||||
}
|
||||
|
||||
self.calendar_storage.create_event(event).await
|
||||
}
|
||||
|
||||
async fn create_event_from_ical(
|
||||
&self,
|
||||
event: CreateEventICalDto,
|
||||
user_id: &str,
|
||||
) -> Result<CalendarEventDto, DomainError> {
|
||||
let user_id = "current_user_id"; // This should come from middleware
|
||||
|
||||
// Check if user has access to the calendar
|
||||
let has_access = self
|
||||
.calendar_storage
|
||||
.check_calendar_access(&event.calendar_id, user_id)
|
||||
.await?;
|
||||
|
||||
if !has_access {
|
||||
return Err(DomainError::new(
|
||||
ErrorKind::AccessDenied,
|
||||
@@ -261,7 +213,6 @@ impl CalendarUseCase for CalendarService {
|
||||
"You don't have permission to add events to this calendar",
|
||||
));
|
||||
}
|
||||
|
||||
self.calendar_storage.create_event_from_ical(event).await
|
||||
}
|
||||
|
||||
@@ -269,18 +220,13 @@ impl CalendarUseCase for CalendarService {
|
||||
&self,
|
||||
event_id: &str,
|
||||
update: UpdateEventDto,
|
||||
user_id: &str,
|
||||
) -> Result<CalendarEventDto, DomainError> {
|
||||
let user_id = "current_user_id"; // This should come from middleware
|
||||
|
||||
// Get the event to find its calendar
|
||||
let event = self.calendar_storage.get_event(event_id).await?;
|
||||
|
||||
// Check if user has access to the calendar
|
||||
let has_access = self
|
||||
.calendar_storage
|
||||
.check_calendar_access(&event.calendar_id, user_id)
|
||||
.await?;
|
||||
|
||||
if !has_access {
|
||||
return Err(DomainError::new(
|
||||
ErrorKind::AccessDenied,
|
||||
@@ -288,22 +234,15 @@ impl CalendarUseCase for CalendarService {
|
||||
"You don't have permission to update events in this calendar",
|
||||
));
|
||||
}
|
||||
|
||||
self.calendar_storage.update_event(event_id, update).await
|
||||
}
|
||||
|
||||
async fn delete_event(&self, event_id: &str) -> Result<(), DomainError> {
|
||||
let user_id = "current_user_id"; // This should come from middleware
|
||||
|
||||
// Get the event to find its calendar
|
||||
async fn delete_event(&self, event_id: &str, user_id: &str) -> Result<(), DomainError> {
|
||||
let event = self.calendar_storage.get_event(event_id).await?;
|
||||
|
||||
// Check if user has access to the calendar
|
||||
let has_access = self
|
||||
.calendar_storage
|
||||
.check_calendar_access(&event.calendar_id, user_id)
|
||||
.await?;
|
||||
|
||||
if !has_access {
|
||||
return Err(DomainError::new(
|
||||
ErrorKind::AccessDenied,
|
||||
@@ -311,28 +250,23 @@ impl CalendarUseCase for CalendarService {
|
||||
"You don't have permission to delete events in this calendar",
|
||||
));
|
||||
}
|
||||
|
||||
self.calendar_storage.delete_event(event_id).await
|
||||
}
|
||||
|
||||
async fn get_event(&self, event_id: &str) -> Result<CalendarEventDto, DomainError> {
|
||||
let user_id = "current_user_id"; // This should come from middleware
|
||||
|
||||
// Get the event
|
||||
async fn get_event(
|
||||
&self,
|
||||
event_id: &str,
|
||||
user_id: &str,
|
||||
) -> Result<CalendarEventDto, DomainError> {
|
||||
let event = self.calendar_storage.get_event(event_id).await?;
|
||||
|
||||
// Check if user has access to the calendar
|
||||
let has_access = self
|
||||
.calendar_storage
|
||||
.check_calendar_access(&event.calendar_id, user_id)
|
||||
.await?;
|
||||
|
||||
// Check if calendar is public
|
||||
let calendar = self
|
||||
.calendar_storage
|
||||
.get_calendar(&event.calendar_id)
|
||||
.await?;
|
||||
|
||||
if !has_access && !calendar.is_public {
|
||||
return Err(DomainError::new(
|
||||
ErrorKind::AccessDenied,
|
||||
@@ -340,7 +274,6 @@ impl CalendarUseCase for CalendarService {
|
||||
"You don't have permission to view events in this calendar",
|
||||
));
|
||||
}
|
||||
|
||||
Ok(event)
|
||||
}
|
||||
|
||||
@@ -349,18 +282,13 @@ impl CalendarUseCase for CalendarService {
|
||||
calendar_id: &str,
|
||||
limit: Option<i64>,
|
||||
offset: Option<i64>,
|
||||
user_id: &str,
|
||||
) -> Result<Vec<CalendarEventDto>, DomainError> {
|
||||
let user_id = "current_user_id"; // This should come from middleware
|
||||
|
||||
// Check if user has access to the calendar
|
||||
let has_access = self
|
||||
.calendar_storage
|
||||
.check_calendar_access(calendar_id, user_id)
|
||||
.await?;
|
||||
|
||||
// Check if calendar is public
|
||||
let calendar = self.calendar_storage.get_calendar(calendar_id).await?;
|
||||
|
||||
if !has_access && !calendar.is_public {
|
||||
return Err(DomainError::new(
|
||||
ErrorKind::AccessDenied,
|
||||
@@ -368,12 +296,9 @@ impl CalendarUseCase for CalendarService {
|
||||
"You don't have permission to view events in this calendar",
|
||||
));
|
||||
}
|
||||
|
||||
// Use pagination if provided
|
||||
if limit.is_some() || offset.is_some() {
|
||||
let limit = limit.unwrap_or(100);
|
||||
let offset = offset.unwrap_or(0);
|
||||
|
||||
self.calendar_storage
|
||||
.list_events_by_calendar_paginated(calendar_id, limit, offset)
|
||||
.await
|
||||
@@ -389,148 +314,6 @@ impl CalendarUseCase for CalendarService {
|
||||
calendar_id: &str,
|
||||
start: DateTime<Utc>,
|
||||
end: DateTime<Utc>,
|
||||
) -> Result<Vec<CalendarEventDto>, DomainError> {
|
||||
let user_id = "current_user_id"; // This should come from middleware
|
||||
|
||||
// Check if user has access to the calendar
|
||||
let has_access = self
|
||||
.calendar_storage
|
||||
.check_calendar_access(calendar_id, user_id)
|
||||
.await?;
|
||||
|
||||
// Check if calendar is public
|
||||
let calendar = self.calendar_storage.get_calendar(calendar_id).await?;
|
||||
|
||||
if !has_access && !calendar.is_public {
|
||||
return Err(DomainError::new(
|
||||
ErrorKind::AccessDenied,
|
||||
"Calendar",
|
||||
"You don't have permission to view events in this calendar",
|
||||
));
|
||||
}
|
||||
|
||||
self.calendar_storage
|
||||
.get_events_in_time_range(calendar_id, &start, &end)
|
||||
.await
|
||||
}
|
||||
|
||||
// ─── User-contextualized variants (for CalDAV protocol handler) ──
|
||||
|
||||
async fn create_calendar_for_user(
|
||||
&self,
|
||||
calendar: CreateCalendarDto,
|
||||
user_id: &str,
|
||||
) -> Result<CalendarDto, DomainError> {
|
||||
self.calendar_storage
|
||||
.create_calendar(calendar, user_id)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn update_calendar_for_user(
|
||||
&self,
|
||||
calendar_id: &str,
|
||||
update: UpdateCalendarDto,
|
||||
user_id: &str,
|
||||
) -> Result<CalendarDto, DomainError> {
|
||||
let has_access = self
|
||||
.calendar_storage
|
||||
.check_calendar_access(calendar_id, user_id)
|
||||
.await?;
|
||||
if !has_access {
|
||||
return Err(DomainError::new(
|
||||
ErrorKind::AccessDenied,
|
||||
"Calendar",
|
||||
"You don't have permission to update this calendar",
|
||||
));
|
||||
}
|
||||
self.calendar_storage
|
||||
.update_calendar(calendar_id, update)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn delete_calendar_for_user(
|
||||
&self,
|
||||
calendar_id: &str,
|
||||
user_id: &str,
|
||||
) -> Result<(), DomainError> {
|
||||
let has_access = self
|
||||
.calendar_storage
|
||||
.check_calendar_access(calendar_id, user_id)
|
||||
.await?;
|
||||
if !has_access {
|
||||
return Err(DomainError::new(
|
||||
ErrorKind::AccessDenied,
|
||||
"Calendar",
|
||||
"You don't have permission to delete this calendar",
|
||||
));
|
||||
}
|
||||
self.calendar_storage.delete_calendar(calendar_id).await
|
||||
}
|
||||
|
||||
async fn get_calendar_for_user(
|
||||
&self,
|
||||
calendar_id: &str,
|
||||
user_id: &str,
|
||||
) -> Result<CalendarDto, DomainError> {
|
||||
let calendar = self.calendar_storage.get_calendar(calendar_id).await?;
|
||||
let has_access = self
|
||||
.calendar_storage
|
||||
.check_calendar_access(calendar_id, user_id)
|
||||
.await?;
|
||||
if !has_access && !calendar.is_public {
|
||||
return Err(DomainError::new(
|
||||
ErrorKind::AccessDenied,
|
||||
"Calendar",
|
||||
"You don't have permission to view this calendar",
|
||||
));
|
||||
}
|
||||
Ok(calendar)
|
||||
}
|
||||
|
||||
async fn list_my_calendars_for_user(
|
||||
&self,
|
||||
user_id: &str,
|
||||
) -> Result<Vec<CalendarDto>, DomainError> {
|
||||
self.calendar_storage.list_calendars_by_owner(user_id).await
|
||||
}
|
||||
|
||||
async fn list_events_for_user(
|
||||
&self,
|
||||
calendar_id: &str,
|
||||
limit: Option<i64>,
|
||||
offset: Option<i64>,
|
||||
user_id: &str,
|
||||
) -> Result<Vec<CalendarEventDto>, DomainError> {
|
||||
let has_access = self
|
||||
.calendar_storage
|
||||
.check_calendar_access(calendar_id, user_id)
|
||||
.await?;
|
||||
let calendar = self.calendar_storage.get_calendar(calendar_id).await?;
|
||||
if !has_access && !calendar.is_public {
|
||||
return Err(DomainError::new(
|
||||
ErrorKind::AccessDenied,
|
||||
"Calendar",
|
||||
"You don't have permission to view events in this calendar",
|
||||
));
|
||||
}
|
||||
if limit.is_some() || offset.is_some() {
|
||||
let limit = limit.unwrap_or(100);
|
||||
let offset = offset.unwrap_or(0);
|
||||
self.calendar_storage
|
||||
.list_events_by_calendar_paginated(calendar_id, limit, offset)
|
||||
.await
|
||||
} else {
|
||||
self.calendar_storage
|
||||
.list_events_by_calendar(calendar_id)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
async fn get_events_in_range_for_user(
|
||||
&self,
|
||||
calendar_id: &str,
|
||||
start: DateTime<Utc>,
|
||||
end: DateTime<Utc>,
|
||||
user_id: &str,
|
||||
) -> Result<Vec<CalendarEventDto>, DomainError> {
|
||||
let has_access = self
|
||||
@@ -549,43 +332,4 @@ impl CalendarUseCase for CalendarService {
|
||||
.get_events_in_time_range(calendar_id, &start, &end)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn create_event_from_ical_for_user(
|
||||
&self,
|
||||
event: CreateEventICalDto,
|
||||
user_id: &str,
|
||||
) -> Result<CalendarEventDto, DomainError> {
|
||||
let has_access = self
|
||||
.calendar_storage
|
||||
.check_calendar_access(&event.calendar_id, user_id)
|
||||
.await?;
|
||||
if !has_access {
|
||||
return Err(DomainError::new(
|
||||
ErrorKind::AccessDenied,
|
||||
"Calendar",
|
||||
"You don't have permission to add events to this calendar",
|
||||
));
|
||||
}
|
||||
self.calendar_storage.create_event_from_ical(event).await
|
||||
}
|
||||
|
||||
async fn delete_event_for_user(
|
||||
&self,
|
||||
event_id: &str,
|
||||
user_id: &str,
|
||||
) -> Result<(), DomainError> {
|
||||
let event = self.calendar_storage.get_event(event_id).await?;
|
||||
let has_access = self
|
||||
.calendar_storage
|
||||
.check_calendar_access(&event.calendar_id, user_id)
|
||||
.await?;
|
||||
if !has_access {
|
||||
return Err(DomainError::new(
|
||||
ErrorKind::AccessDenied,
|
||||
"Calendar",
|
||||
"You don't have permission to delete events in this calendar",
|
||||
));
|
||||
}
|
||||
self.calendar_storage.delete_event(event_id).await
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user