devcycle_bucketing_rs/user/
user.rs1use crate::config::platform_data::PlatformData;
2use crate::config::{Environment, Project};
3use crate::feature::{Feature, FeatureVariation, ReadOnlyVariable};
4use chrono::{DateTime, Utc};
5use serde::{Deserialize, Serialize};
6use std::collections::HashMap;
7use std::sync::Arc;
8
9#[derive(Serialize, Deserialize, Clone)]
10#[serde(rename_all = "camelCase")]
11pub struct User {
12 pub user_id: String,
14 pub email: String,
16 pub name: String,
18 pub language: String,
20 pub country: String,
22 pub app_version: String,
24 pub app_build: String,
26 pub custom_data: HashMap<String, serde_json::Value>,
28 pub private_custom_data: HashMap<String, serde_json::Value>,
30 pub device_model: String,
32 #[serde(default = "Utc::now")]
34 pub last_seen_date: DateTime<Utc>,
35}
36
37impl User {
38 pub fn get_populated_user(&self, sdk_key: &str) -> PopulatedUser {
39 self.get_populated_user_with_platform_data_and_time(sdk_key, None, Utc::now())
40 }
41
42 pub fn get_populated_user_with_platform_data_and_time(
43 &self,
44 sdk_key: &str,
45 platform_data: Option<Arc<PlatformData>>,
46 create_date: DateTime<Utc>,
47 ) -> PopulatedUser {
48 let platform_data = platform_data
49 .unwrap_or_else(|| crate::config::platform_data::get_platform_data(sdk_key).unwrap());
50
51 PopulatedUser {
52 user_id: self.user_id.clone(),
53 email: self.email.clone(),
54 name: self.name.clone(),
55 private_custom_data: self.private_custom_data.clone(),
56 custom_data: self.custom_data.clone(),
57 language: self.language.clone(),
58 country: self.country.clone(),
59 app_version: self.app_version.clone(),
60 app_build: self.app_build.clone(),
61 device_model: self.device_model.clone(),
62 last_seen_date: self.last_seen_date.clone(),
63 platform_data,
64 created_date: create_date,
65 }
66 }
67}
68
69pub struct UserFeatureData<'a> {
70 user: &'a User,
71 feature_vars: &'a HashMap<String, String>,
72}
73
74#[derive(Clone, Serialize, Deserialize)]
75#[serde(rename_all = "camelCase")]
76pub struct PopulatedUser {
77 #[serde(rename = "userId")]
78 pub user_id: String,
79 pub email: String,
81 pub name: String,
83 pub language: String,
85 pub country: String,
87 #[serde(rename = "appVersion")]
89 pub app_version: String,
90 #[serde(rename = "appBuild")]
92 pub app_build: String,
93 #[serde(rename = "customData")]
95 pub custom_data: HashMap<String, serde_json::Value>,
96 #[serde(rename = "privateCustomData")]
98 pub private_custom_data: HashMap<String, serde_json::Value>,
99 #[serde(rename = "deviceModel")]
101 pub device_model: String,
102 #[serde(rename = "lastSeenDate")]
104 pub last_seen_date: DateTime<Utc>,
105 #[serde(rename = "platformData")]
107 pub platform_data: Arc<PlatformData>,
108 #[serde(rename = "createdDate")]
110 pub created_date: DateTime<Utc>,
111}
112
113impl PopulatedUser {
114 pub fn merge_client_custom_data(
115 mut self,
116 client_custom_data: HashMap<String, serde_json::Value>,
117 ) {
118 for (k, v) in client_custom_data {
119 if !self.custom_data.contains_key(&k) && !self.private_custom_data.contains_key(&k) {
120 self.custom_data.insert(k, v);
121 }
122 }
123 }
124
125 pub fn combined_custom_data(&self) -> HashMap<String, serde_json::Value> {
126 let mut ret = HashMap::new();
127 if !self.custom_data.is_empty() {
128 ret.extend(self.custom_data.clone());
129 }
130 if !self.private_custom_data.is_empty() {
131 ret.extend(self.private_custom_data.clone());
132 }
133 ret
134 }
135 pub fn new(
136 user: User,
137 platform_data: Arc<PlatformData>,
138 client_custom_data: HashMap<String, serde_json::Value>,
139 ) -> PopulatedUser {
140 let mut popuser = PopulatedUser {
141 user_id: user.user_id.clone(),
142 email: user.email.clone(),
143 name: user.name.clone(),
144 private_custom_data: user.private_custom_data.clone(),
145 custom_data: user.custom_data.clone(),
146 language: user.language,
147 country: user.country.clone(),
148 app_version: user.app_version.clone(),
149 app_build: user.app_build.clone(),
150 device_model: user.device_model.clone(),
151 last_seen_date: user.last_seen_date.clone(),
152 platform_data,
153 created_date: Utc::now(),
154 };
155 for (k, v) in client_custom_data {
156 if !popuser.custom_data.contains_key(&k)
157 && !popuser.private_custom_data.contains_key(&k)
158 {
159 popuser.custom_data.insert(k, v);
160 }
161 }
162
163 return popuser;
164 }
165}
166
167#[derive(Serialize)]
168#[serde(rename_all = "camelCase")]
169pub struct BucketedUserConfig {
170 pub(crate) project: Project,
171 pub(crate) environment: Environment,
172 pub(crate) features: HashMap<String, Feature>,
173 pub(crate) feature_variation_map: HashMap<String, String>,
174 pub(crate) variable_variation_map: HashMap<String, FeatureVariation>,
175 pub(crate) variables: HashMap<String, ReadOnlyVariable>,
176 #[serde(skip_serializing)]
177 pub(crate) user: PopulatedUser,
178}