Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F3341475
D8938.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
5 KB
Referenced Files
None
Subscribers
None
D8938.diff
View Options
diff --git a/services/reports/Cargo.lock b/services/reports/Cargo.lock
--- a/services/reports/Cargo.lock
+++ b/services/reports/Cargo.lock
@@ -1377,6 +1377,7 @@
dependencies = [
"anyhow",
"aws-config",
+ "aws-sdk-dynamodb",
"chrono",
"clap",
"comm-services-lib",
diff --git a/services/reports/Cargo.toml b/services/reports/Cargo.toml
--- a/services/reports/Cargo.toml
+++ b/services/reports/Cargo.toml
@@ -9,6 +9,7 @@
[dependencies]
anyhow = "1.0"
aws-config = "0.55"
+aws-sdk-dynamodb = "0.27"
chrono = { version = "0.4", features = ["serde"] }
clap = { version = "4.0", features = ["derive", "env"] }
comm-services-lib = { path = "../comm-services-lib", features = [
diff --git a/services/reports/src/database/item.rs b/services/reports/src/database/item.rs
new file mode 100644
--- /dev/null
+++ b/services/reports/src/database/item.rs
@@ -0,0 +1,116 @@
+use aws_sdk_dynamodb::types::AttributeValue;
+use comm_services_lib::database::{self, DBItemError, TryFromAttribute};
+use num_traits::FromPrimitive;
+use tracing::debug;
+
+use super::constants::*;
+
+use crate::report_types::*;
+
+// DB conversions for report types
+
+// ReportID
+impl From<ReportID> for AttributeValue {
+ fn from(value: ReportID) -> Self {
+ AttributeValue::S(value.into())
+ }
+}
+impl From<&ReportID> for AttributeValue {
+ fn from(value: &ReportID) -> Self {
+ AttributeValue::S(value.clone().into())
+ }
+}
+impl TryFrom<Option<AttributeValue>> for ReportID {
+ type Error = database::DBItemError;
+
+ fn try_from(value: Option<AttributeValue>) -> Result<Self, Self::Error> {
+ let raw = String::try_from_attr(ATTR_REPORT_ID, value)?;
+ Ok(ReportID::from(raw))
+ }
+}
+
+// ReportType
+impl From<ReportType> for AttributeValue {
+ fn from(value: ReportType) -> Self {
+ let num = value as u8;
+ AttributeValue::N(num.to_string())
+ }
+}
+impl TryFromAttribute for ReportType {
+ fn try_from_attr(
+ attribute_name: impl Into<String>,
+ attribute: Option<AttributeValue>,
+ ) -> Result<Self, database::DBItemError> {
+ let attr_name = attribute_name.into();
+ let num: u8 = database::parse_int_attribute(&attr_name, attribute)?;
+ <ReportType as FromPrimitive>::from_u8(num).ok_or_else(|| {
+ database::DBItemError::new(
+ attr_name,
+ database::Value::String(num.to_string()),
+ database::DBItemAttributeError::IncorrectType,
+ )
+ })
+ }
+}
+
+// ReportPlatform
+impl From<ReportPlatform> for AttributeValue {
+ fn from(value: ReportPlatform) -> Self {
+ let raw = value.to_string().to_lowercase();
+ AttributeValue::S(raw)
+ }
+}
+impl TryFromAttribute for ReportPlatform {
+ fn try_from_attr(
+ attribute_name: impl Into<String>,
+ attribute: Option<AttributeValue>,
+ ) -> Result<Self, DBItemError> {
+ let attr_name = attribute_name.into();
+ let raw = String::try_from_attr(&attr_name, attribute)?;
+ // serde_json understands only quoted strings
+ let quoted = format!("\"{raw}\"");
+ serde_json::from_str("ed).map_err(|err| {
+ debug!("Failed to deserialize ReportPlatform: {}", err);
+ DBItemError::new(
+ attr_name,
+ database::Value::String(raw),
+ database::DBItemAttributeError::IncorrectType,
+ )
+ })
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use comm_services_lib::database::AttributeTryInto;
+
+ use super::*;
+
+ #[test]
+ fn test_platform_conversions() -> anyhow::Result<()> {
+ let platform = ReportPlatform::MacOS;
+
+ let attribute: AttributeValue = platform.into();
+
+ assert_eq!(attribute, AttributeValue::S("macos".to_string()));
+
+ let converted_back: ReportPlatform =
+ Some(attribute).attr_try_into("foo")?;
+
+ assert!(matches!(converted_back, ReportPlatform::MacOS));
+
+ Ok(())
+ }
+
+ #[test]
+ fn test_type_conversions() -> anyhow::Result<()> {
+ let report_type = ReportType::MediaMission;
+ let numeric_type = (report_type as u8).to_string();
+ let attr: AttributeValue = report_type.into();
+ assert_eq!(attr, AttributeValue::N(numeric_type.to_string()));
+
+ let converted_back: ReportType = Some(attr).attr_try_into("foo")?;
+ assert!(matches!(converted_back, ReportType::MediaMission));
+ Ok(())
+ }
+}
diff --git a/services/reports/src/database/mod.rs b/services/reports/src/database/mod.rs
new file mode 100644
--- /dev/null
+++ b/services/reports/src/database/mod.rs
@@ -0,0 +1,14 @@
+pub mod item;
+
+mod constants {
+ pub const TABLE_NAME: &str = "reports-service-reports";
+
+ pub const ATTR_REPORT_ID: &str = "reportID";
+ pub const ATTR_USER_ID: &str = "userID";
+ pub const ATTR_REPORT_TYPE: &str = "type";
+ pub const ATTR_PLATFORM: &str = "platform";
+ pub const ATTR_BLOB_INFO: &str = "blobInfo";
+ pub const ATTR_REPORT_CONTENT: &str = "content";
+ pub const ATTR_ENCRYPTION_KEY: &str = "encryptionKey";
+ pub const ATTR_CREATION_TIME: &str = "creationTime";
+}
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 database;
pub mod report_types;
use anyhow::Result;
diff --git a/services/terraform/modules/shared/dynamodb.tf b/services/terraform/modules/shared/dynamodb.tf
--- a/services/terraform/modules/shared/dynamodb.tf
+++ b/services/terraform/modules/shared/dynamodb.tf
@@ -289,3 +289,14 @@
type = "S"
}
}
+
+resource "aws_dynamodb_table" "reports-service-reports" {
+ name = "reports-service-reports"
+ hash_key = "reportID"
+ billing_mode = "PAY_PER_REQUEST"
+
+ attribute {
+ name = "reportID"
+ type = "S"
+ }
+}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Nov 22, 11:01 PM (17 h, 58 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2566341
Default Alt Text
D8938.diff (5 KB)
Attached To
Mode
D8938: [report-service] Add report types DB conversions
Attached
Detach File
Event Timeline
Log In to Comment