Page MenuHomePhorge

D8937.1768185283.diff
No OneTemporary

Size
6 KB
Referenced Files
None
Subscribers
None

D8937.1768185283.diff

diff --git a/services/reports/Cargo.lock b/services/reports/Cargo.lock
--- a/services/reports/Cargo.lock
+++ b/services/reports/Cargo.lock
@@ -518,6 +518,7 @@
"iana-time-zone",
"js-sys",
"num-traits",
+ "serde",
"time 0.1.45",
"wasm-bindgen",
"winapi",
@@ -813,6 +814,17 @@
"version_check",
]
+[[package]]
+name = "getrandom"
+version = "0.2.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "wasi 0.11.0+wasi-snapshot-preview1",
+]
+
[[package]]
name = "gimli"
version = "0.28.0"
@@ -1133,6 +1145,17 @@
"winapi",
]
+[[package]]
+name = "num-derive"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9e6a0fd4f737c707bd9086cc16c925f294943eb62eb71499e9fd4cf71f8b9f4e"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.29",
+]
+
[[package]]
name = "num-integer"
version = "0.1.45"
@@ -1354,13 +1377,21 @@
dependencies = [
"anyhow",
"aws-config",
+ "chrono",
"clap",
"comm-services-lib",
+ "derive_more",
+ "num-derive",
+ "num-traits",
"once_cell",
+ "serde",
+ "serde_json",
+ "serde_repr",
"tokio",
"tokio-stream",
"tracing",
"tracing-subscriber",
+ "uuid",
]
[[package]]
@@ -1564,6 +1595,17 @@
"serde",
]
+[[package]]
+name = "serde_repr"
+version = "0.1.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8725e1dfadb3a50f7e5ce0b1a540466f6ed3fe7a0fca2ac2b8b831d31316bd00"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.29",
+]
+
[[package]]
name = "serde_urlencoded"
version = "0.7.1"
@@ -1983,6 +2025,15 @@
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
+[[package]]
+name = "uuid"
+version = "1.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "79daa5ed5740825c40b389c5e50312b9c86df53fccd33f281df655642b43869d"
+dependencies = [
+ "getrandom",
+]
+
[[package]]
name = "valuable"
version = "0.1.0"
diff --git a/services/reports/Cargo.toml b/services/reports/Cargo.toml
--- a/services/reports/Cargo.toml
+++ b/services/reports/Cargo.toml
@@ -9,12 +9,20 @@
[dependencies]
anyhow = "1.0"
aws-config = "0.55"
+chrono = { version = "0.4", features = ["serde"] }
clap = { version = "4.0", features = ["derive", "env"] }
comm-services-lib = { path = "../comm-services-lib", features = [
"blob-client",
] }
+derive_more = "0.99"
+num-traits = "0.2"
+num-derive = "0.4"
once_cell = "1.17"
+serde = { version = "1.0", features = ["derive"] }
+serde_json = "1.0"
+serde_repr = "0.1"
tokio = { version = "1.32", features = ["macros", "rt-multi-thread"] }
tokio-stream = "0.1"
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
+uuid = { version = "1.2", features = ["v4"] }
diff --git a/services/reports/src/main.rs b/services/reports/src/main.rs
--- a/services/reports/src/main.rs
+++ b/services/reports/src/main.rs
@@ -1,4 +1,5 @@
pub mod config;
+pub mod report_types;
use anyhow::Result;
use tracing_subscriber::filter::{EnvFilter, LevelFilter};
diff --git a/services/reports/src/report_types.rs b/services/reports/src/report_types.rs
new file mode 100644
--- /dev/null
+++ b/services/reports/src/report_types.rs
@@ -0,0 +1,114 @@
+// Report ID
+
+use std::collections::HashMap;
+
+use chrono::{serde::ts_milliseconds_option, DateTime, Utc};
+use derive_more::{Deref, Display, Into};
+use num_derive::FromPrimitive;
+use serde::{de::Error, Deserialize, Serialize};
+use serde_repr::Deserialize_repr;
+
+#[derive(Clone, Debug, Deref, Serialize, Into)]
+#[repr(transparent)]
+pub struct ReportID(String);
+impl Default for ReportID {
+ fn default() -> Self {
+ let uuid = uuid::Uuid::new_v4();
+ ReportID(uuid.to_string())
+ }
+}
+impl From<String> for ReportID {
+ fn from(value: String) -> Self {
+ ReportID(value)
+ }
+}
+
+/// Serialized / deserialized report type.
+/// We receive report type from clients as a number,
+/// but want to display it as a string.
+#[derive(
+ Copy, Clone, Debug, Default, FromPrimitive, Serialize, Deserialize_repr,
+)]
+#[repr(u8)]
+#[serde(rename_all(serialize = "snake_case"))]
+pub enum ReportType {
+ // NOTE: Keep these in sync with `reportTypes` in lib/types/report-types.js
+ #[default]
+ ErrorReport = 0,
+ ThreadInconsistency = 1,
+ EntryInconsistency = 2,
+ MediaMission = 3,
+ UserInconsistency = 4,
+}
+
+/// Report platform
+#[derive(Clone, Debug, Serialize, Deserialize, Display)]
+#[serde(rename_all = "lowercase")]
+pub enum ReportPlatform {
+ Android,
+ IOS,
+ Web,
+ Windows,
+ MacOS,
+}
+
+#[derive(Debug, Serialize, Deserialize)]
+#[serde(rename_all = "camelCase")]
+pub struct PlatformDetails {
+ pub platform: ReportPlatform,
+ code_version: Option<u16>,
+ state_version: Option<u16>,
+}
+
+/// Input report payload - this is the JSON we receive from clients
+#[derive(Debug, Deserialize)]
+#[serde(rename_all = "camelCase")]
+#[serde(remote = "Self")] // we delegate to our custom validation trait
+pub struct ReportInput {
+ pub platform_details: PlatformDetails,
+
+ #[serde(rename = "type")]
+ #[serde(default)]
+ pub report_type: ReportType,
+
+ #[serde(default)]
+ #[serde(with = "ts_milliseconds_option")]
+ pub time: Option<DateTime<Utc>>,
+
+ // we usually don't care about the rest of the fields
+ // so we just keep them as a JSON object
+ #[serde(flatten)]
+ pub report_content: HashMap<String, serde_json::Value>,
+}
+
+// We can do additional validation here
+impl<'de> serde::de::Deserialize<'de> for ReportInput {
+ fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
+ where
+ D: serde::Deserializer<'de>,
+ {
+ let mut this = Self::deserialize(deserializer)?;
+ if this.time.is_none() {
+ if !matches!(this.report_type, ReportType::ThreadInconsistency) {
+ return Err(Error::custom(
+ "The 'time' field is optional only for thread inconsistency reports",
+ ));
+ }
+ this.time = Some(Utc::now());
+ }
+ Ok(this)
+ }
+}
+
+/// Report output payload - this is used to view the report
+#[derive(Debug, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct ReportOutput {
+ pub id: ReportID,
+ #[serde(rename = "userID")]
+ pub user_id: String,
+ pub platform: ReportPlatform,
+ pub report_type: ReportType,
+ pub creation_time: DateTime<Utc>,
+ pub content: HashMap<String, serde_json::Value>,
+}

File Metadata

Mime Type
text/plain
Expires
Mon, Jan 12, 2:34 AM (9 h, 17 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5921318
Default Alt Text
D8937.1768185283.diff (6 KB)

Event Timeline