diff --git a/profiles/src/apub/results/report.rs b/profiles/src/apub/results/report.rs index 799c83a..db75a06 100644 --- a/profiles/src/apub/results/report.rs +++ b/profiles/src/apub/results/report.rs @@ -58,7 +58,11 @@ impl Outbound for ReportCreated { } fn inboxes(&self, ctx: &Context) -> Result, Error> { - let report = ctx.store.reports.by_id(self.report_id)?; + let report = ctx + .store + .reports + .by_id(self.report_id)? + .req("report by id")?; let server_id = server_from_report(&report, ctx)?; @@ -73,7 +77,11 @@ impl Outbound for ReportCreated { } fn to_apub(&self, ctx: &Context) -> Result { - let report = ctx.store.reports.by_id(self.report_id)?; + let report = ctx + .store + .reports + .by_id(self.report_id)? + .req("report by id")?; let server_id = server_from_report(&report, ctx)?; let actor_id = ctx .apub diff --git a/profiles/src/store/report.rs b/profiles/src/store/report.rs index 461c3ab..3b092fc 100644 --- a/profiles/src/store/report.rs +++ b/profiles/src/store/report.rs @@ -180,45 +180,133 @@ impl Store { Ok(report) } - pub fn all(&self) -> impl DoubleEndedIterator { - self.created_open_report - .iter() + pub fn open_reports(&self) -> impl DoubleEndedIterator { + let start: &[u8] = &[]; + self.open_reports_date_range(start..).rev() + } + + pub fn closed_reports(&self) -> impl DoubleEndedIterator { + let start: &[u8] = &[]; + self.closed_reports_date_range(start..).rev() + } + + pub fn open_reports_newer_than<'a>( + &'a self, + id: Uuid, + ) -> impl DoubleEndedIterator + 'a { + self.report_created + .get(id.as_bytes()) + .ok() + .and_then(|opt| opt) + .and_then(date_from_ivec) + .into_iter() + .flat_map(move |created| { + self.open_reports_date_range(created_open_reports_bound(created)..) + }) + } + + pub fn open_reports_older_than<'a>( + &'a self, + id: Uuid, + ) -> impl DoubleEndedIterator + 'a { + self.report_created + .get(id.as_bytes()) + .ok() + .and_then(|opt| opt) + .and_then(date_from_ivec) + .into_iter() + .flat_map(move |created| { + self.open_reports_date_range(..created_open_reports_bound(created)) + }) + .rev() + } + + pub fn closed_reports_newer_than<'a>( + &'a self, + id: Uuid, + ) -> impl DoubleEndedIterator + 'a { + self.report_resolved + .get(id.as_bytes()) + .ok() + .and_then(|opt| opt) + .and_then(date_from_ivec) + .into_iter() + .flat_map(move |resolved| { + self.closed_reports_date_range(resolved_resolved_reports_bound(resolved)..) + }) + } + + pub fn closed_reports_older_than<'a>( + &'a self, + id: Uuid, + ) -> impl DoubleEndedIterator + 'a { + self.report_resolved + .get(id.as_bytes()) + .ok() + .and_then(|opt| opt) + .and_then(date_from_ivec) + .into_iter() + .flat_map(move |resolved| { + self.closed_reports_date_range(..resolved_resolved_reports_bound(resolved)) + }) + .rev() + } + + fn closed_reports_date_range( + &self, + range: impl std::ops::RangeBounds, + ) -> impl DoubleEndedIterator + where + K: AsRef<[u8]>, + { + self.resolved_resolved_report + .range(range) .values() .filter_map(|res| res.ok()) .filter_map(uuid_from_ivec) } - pub fn by_id(&self, id: Uuid) -> Result { + fn open_reports_date_range( + &self, + range: impl std::ops::RangeBounds, + ) -> impl DoubleEndedIterator + where + K: AsRef<[u8]>, + { + self.created_open_report + .range(range) + .values() + .filter_map(|res| res.ok()) + .filter_map(uuid_from_ivec) + } + + pub fn by_id(&self, id: Uuid) -> Result, StoreError> { let reporter_kind = self .report_reporter_kind .get(id.as_bytes())? - .and_then(reporter_kind_from_ivec) - .ok_or_else(|| StoreError::Missing)?; - let reporter_opt = match reporter_kind { - ReporterKind::Profile => self.report_profile.get(id.as_bytes())?, - ReporterKind::Server => self.report_server.get(id.as_bytes())?, - }; + .and_then(reporter_kind_from_ivec); - let reporter = reporter_opt - .and_then(uuid_from_ivec) - .ok_or_else(|| StoreError::Missing)?; + let reporter_opt = match reporter_kind { + Some(ReporterKind::Profile) => self.report_profile.get(id.as_bytes())?, + Some(ReporterKind::Server) => self.report_server.get(id.as_bytes())?, + None => None, + }; + let reporter = reporter_opt.and_then(uuid_from_ivec); let kind = self .report_kind .get(id.as_bytes())? - .and_then(kind_from_ivec) - .ok_or_else(|| StoreError::Missing)?; + .and_then(kind_from_ivec); let reported_item_opt = match kind { - ReportKind::Profile => self.report_reported_profile.get(id.as_bytes())?, - ReportKind::Submission => self.report_reported_submission.get(id.as_bytes())?, - ReportKind::Comment => self.report_reported_comment.get(id.as_bytes())?, - ReportKind::Post => self.report_reported_post.get(id.as_bytes())?, + Some(ReportKind::Profile) => self.report_reported_profile.get(id.as_bytes())?, + Some(ReportKind::Submission) => self.report_reported_submission.get(id.as_bytes())?, + Some(ReportKind::Comment) => self.report_reported_comment.get(id.as_bytes())?, + Some(ReportKind::Post) => self.report_reported_post.get(id.as_bytes())?, + None => None, }; - let reported_item = reported_item_opt - .and_then(uuid_from_ivec) - .ok_or_else(|| StoreError::Missing)?; + let reported_item = reported_item_opt.and_then(uuid_from_ivec); let note = self.report_note.get(id.as_bytes())?.map(string_from_ivec); @@ -235,17 +323,21 @@ impl Store { .get(id.as_bytes())? .and_then(date_from_ivec); - Ok(Report { - id, - reporter, - reporter_kind, - reported_item, - kind, - note, - resolved, - resolution, - forwarded, - }) + let optionable = move || -> Option { + Some(Report { + id, + reporter: reporter?, + reporter_kind: reporter_kind?, + reported_item: reported_item?, + kind: kind?, + note, + resolved, + resolution, + forwarded, + }) + }; + + Ok((optionable)()) } pub(crate) fn forwarded(&self, report_id: Uuid) -> Result>, StoreError> { @@ -371,6 +463,10 @@ fn created_open_reports_key(created_at: DateTime, report_id: Uuid) -> Strin format!("/created/{}/report/{}", created_at.to_rfc3339(), report_id) } +fn created_open_reports_bound(created_at: DateTime) -> String { + format!("/created/{}/report/", created_at.to_rfc3339()) +} + fn resolved_resolved_reports_key(resolved_at: DateTime, report_id: Uuid) -> String { format!( "/resolved/{}/report/{}", @@ -378,3 +474,7 @@ fn resolved_resolved_reports_key(resolved_at: DateTime, report_id: Uuid) -> report_id ) } + +fn resolved_resolved_reports_bound(resolved_at: DateTime) -> String { + format!("/resolved/{}/report/", resolved_at.to_rfc3339()) +} diff --git a/profiles/src/viewer.rs b/profiles/src/viewer.rs index 1bd86dc..f8a0031 100644 --- a/profiles/src/viewer.rs +++ b/profiles/src/viewer.rs @@ -64,7 +64,7 @@ impl Viewer { Ok(true) } (Viewer::Server(viewer_id), StoredRecords::Report(report_id)) => { - let report = ctx.store.reports.by_id(report_id)?; + let report = ctx.store.reports.by_id(report_id)?.req("report by id")?; let server_id = item_server_for_report(&report, ctx)?; if *viewer_id == server_id {