Skip to content
This repository was archived by the owner on Feb 24, 2025. It is now read-only.

Commit 0e788c9

Browse files
committed
feat: change the data struct
1 parent e1d0ef5 commit 0e788c9

14 files changed

+222
-237
lines changed

.idea/.gitignore

+5
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/modules.xml

+8
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/vcs.xml

+6
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/zvms4-backend-rust.iml

+11
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.lock

+26-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+3-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ edition = "2021"
77

88
[dependencies]
99
aes = "0.8.4"
10+
anyhow = "1.0.86"
1011
axum = "0.7.5"
1112
axum-core = "0.4.3"
1213
axum-extra = { version = "0.9.3", features = [
@@ -25,6 +26,7 @@ chrono = { version = "0.4.38", features = ["serde"] }
2526
futures = "0.3.30"
2627
hex = { version = "0.4.3", features = ["serde"] }
2728
jsonwebtoken = "9.3.0"
29+
magic = "0.16.2"
2830
mongodb = { version = "2.8.2", features = ["async-std"] }
2931
once_cell = "1.19.0"
3032
pem = { version = "3.0.4", features = ["serde"] }
@@ -33,7 +35,7 @@ pyo3 = { version = "0.21.2", features = ["auto-initialize"] }
3335
rand = "0.8.5"
3436
reqwest = "0.12.3"
3537
rsa = "0.9.6"
36-
serde = "1.0.198"
38+
serde = { version = "1.0.198", features = ["derive"] }
3739
serde_json = "1.0.116"
3840
serde_qs = { version = "0.13.0", features = ["axum"] }
3941
socketioxide = { version = "0.12.0", features = [

src/main.rs

+1-50
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,12 @@ mod calc;
33
mod database;
44
mod launch;
55
mod models;
6-
mod routers;
6+
// mod routers;
77
mod tests;
88
mod utils;
99
use crate::models::exports::ExportState;
1010
use axum::{
1111
http::Method,
12-
routing::{delete, get, post, put},
1312
Extension, Router,
1413
};
1514
use launch::{generate_aes_key, generate_rsa_keypair};
@@ -64,54 +63,6 @@ async fn main() {
6463

6564
// Set up the router
6665
let app = Router::new()
67-
.route("/activity/", get(routers::activities::read::read_all))
68-
.route(
69-
"/activity/",
70-
post(routers::activities::insert::insert_activity),
71-
)
72-
.route("/activity/:id", get(routers::activities::read::read_one))
73-
.route(
74-
"/activity/:id",
75-
delete(routers::activities::remove::remove_activity),
76-
)
77-
.route(
78-
"/activity/:id/name",
79-
put(routers::activities::update::update_activity_name),
80-
)
81-
.route(
82-
"/activity/:id/description",
83-
put(routers::activities::update::update_activity_description),
84-
)
85-
.route(
86-
"/activity/:id/member/:member_id",
87-
get(routers::activities::members::read::read_member),
88-
)
89-
.route(
90-
"/activity/:id/member",
91-
post(routers::activities::members::insert::insert_member_into_activity),
92-
)
93-
.route(
94-
"/activity/:id/member/:member_id/status",
95-
put(routers::activities::members::update::update_member_status),
96-
)
97-
.route(
98-
"/activity/:id/member/:member_id/impression",
99-
put(routers::activities::members::update::update_member_impression),
100-
)
101-
.route("/user/auth", post(routers::auth::login))
102-
.route(
103-
"/user/:user_id/activity",
104-
get(routers::users::activity::read_user_activities),
105-
)
106-
.route(
107-
"/user/:user_id/time",
108-
get(routers::users::time::calculate_user_activity_time),
109-
)
110-
.route("/export", post(routers::exports::export_activity_times))
111-
.route(
112-
"/export/:task_id",
113-
get(routers::exports::query_export_status),
114-
)
11566
.layer(Extension(shared_client.clone()))
11667
.layer(Extension(shared_export_state.clone()))
11768
.layer(

src/models/activities.rs

+5-161
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,6 @@
1-
use crate::utils::config::load_config_sync;
2-
use bson::oid::ObjectId;
3-
use chrono::{DateTime, NaiveDateTime, TimeZone};
4-
use serde::{
5-
de::{self, Visitor},
6-
Deserialize, Deserializer, Serialize, Serializer,
7-
};
8-
use std::{fmt, str::FromStr};
1+
use crate::models::utils::datetime_or_u64;
2+
use mongodb::bson::oid::ObjectId;
3+
use serde::{Deserialize, Serialize};
94

105
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, Hash)]
116
#[serde(rename_all = "kebab-case")]
@@ -24,24 +19,6 @@ pub enum ActivityStatus {
2419
Refused,
2520
}
2621

27-
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, Hash)]
28-
#[serde(rename_all = "kebab-case")]
29-
pub enum ActivityMemberStatus {
30-
Effective,
31-
Pending,
32-
Refused,
33-
Rejected,
34-
Draft,
35-
}
36-
37-
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, Hash)]
38-
#[serde(rename_all = "kebab-case")]
39-
pub enum ActivityMode {
40-
OnCampus,
41-
OffCampus,
42-
SocialPractice,
43-
}
44-
4522
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, Hash)]
4623
#[serde(rename_all = "kebab-case")]
4724
pub enum SpecialActivityCategory {
@@ -52,81 +29,9 @@ pub enum SpecialActivityCategory {
5229
Other,
5330
}
5431

55-
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
56-
pub struct ActivityMember {
57-
#[serde(
58-
serialize_with = "objectid_to_string",
59-
deserialize_with = "string_to_objectid"
60-
)]
61-
pub _id: ObjectId, // ObjectId
62-
pub status: ActivityMemberStatus,
63-
pub impression: Option<String>,
64-
pub duration: f64,
65-
pub mode: ActivityMode,
66-
pub history: Option<Vec<ActivityMemberHistory>>,
67-
pub images: Option<Vec<String>>,
68-
}
69-
70-
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
71-
pub struct ActivityMemberHistory {
72-
pub impression: String,
73-
pub duration: f64,
74-
pub time: String,
75-
#[serde(
76-
serialize_with = "objectid_to_string",
77-
deserialize_with = "string_to_objectid"
78-
)]
79-
pub actioner: ObjectId, // ObjectId
80-
pub action: ActivityMemberStatus,
81-
}
82-
83-
pub fn objectid_to_string<S>(value: &ObjectId, serializer: S) -> Result<S::Ok, S::Error>
84-
where
85-
S: Serializer,
86-
{
87-
serializer.serialize_str(&value.to_hex())
88-
}
89-
90-
pub fn string_to_objectid<'de, D>(deserializer: D) -> Result<ObjectId, D::Error>
91-
where
92-
D: Deserializer<'de>,
93-
{
94-
struct ObjectIdOrStringVisitor;
95-
96-
impl<'de> Visitor<'de> for ObjectIdOrStringVisitor {
97-
type Value = ObjectId;
98-
99-
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
100-
formatter.write_str("string or ObjectId")
101-
}
102-
103-
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
104-
where
105-
E: de::Error,
106-
{
107-
ObjectId::from_str(v).map_err(de::Error::custom)
108-
}
109-
110-
fn visit_map<M>(self, mut map: M) -> Result<Self::Value, M::Error>
111-
where
112-
M: de::MapAccess<'de>,
113-
{
114-
if let Some((key, value)) = map.next_entry::<String, String>()? {
115-
if key == "$oid" {
116-
return self.visit_str(&value);
117-
}
118-
}
119-
Err(de::Error::custom("expected a map with a key of '$oid'"))
120-
}
121-
}
122-
123-
deserializer.deserialize_any(ObjectIdOrStringVisitor)
124-
}
125-
12632
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
12733
#[serde(rename_all = "camelCase")]
12834
pub struct Activity {
129-
#[serde(rename = "_id")]
13035
pub _id: ObjectId,
13136
#[serde(rename = "type")]
13237
pub activity_type: ActivityType,
@@ -138,70 +43,9 @@ pub struct Activity {
13843
pub created_at: u64,
13944
#[serde(deserialize_with = "datetime_or_u64")]
14045
pub updated_at: u64,
141-
#[serde(
142-
serialize_with = "objectid_to_string",
143-
deserialize_with = "string_to_objectid"
144-
)]
145-
pub creator: ObjectId, // ObjectId
46+
pub creator: ObjectId,
14647
pub status: ActivityStatus,
147-
pub members: Option<Vec<ActivityMember>>,
48+
pub members: Vec<ObjectId>,
14849
pub location: Option<String>,
14950
pub category: Option<SpecialActivityCategory>,
15051
}
151-
152-
pub fn datetime_or_u64<'de, D>(deserializer: D) -> Result<u64, D::Error>
153-
where
154-
D: Deserializer<'de>,
155-
{
156-
struct DateTimeOrU64 {
157-
timezone: chrono::FixedOffset,
158-
}
159-
160-
impl<'de> Visitor<'de> for DateTimeOrU64 {
161-
type Value = u64;
162-
163-
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
164-
formatter.write_str("a UNIX timestamp as a u64 or a datetime string")
165-
}
166-
167-
fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
168-
where
169-
E: de::Error,
170-
{
171-
Ok(value)
172-
}
173-
174-
fn visit_i64<E>(self, value: i64) -> Result<Self::Value, E>
175-
where
176-
E: de::Error,
177-
{
178-
Ok(value as u64)
179-
}
180-
181-
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
182-
where
183-
E: de::Error,
184-
{
185-
if let Ok(dt) = DateTime::parse_from_rfc3339(value) {
186-
Ok(dt.timestamp() as u64)
187-
} else if let Ok(naive_dt) = NaiveDateTime::parse_from_str(value, "%Y-%m-%d %H:%M:%S") {
188-
let dt = self
189-
.timezone
190-
.from_local_datetime(&naive_dt)
191-
.single()
192-
.ok_or_else(|| {
193-
de::Error::custom("Invalid datetime for the specified timezone")
194-
})?;
195-
Ok(dt.timestamp() as u64)
196-
} else {
197-
Err(de::Error::custom("Invalid datetime format"))
198-
}
199-
}
200-
}
201-
202-
let config = load_config_sync().unwrap();
203-
let offset: i32 = config.timezone.parse().unwrap();
204-
let timezone = chrono::FixedOffset::east_opt(offset * 3600).unwrap();
205-
let visitor = DateTimeOrU64 { timezone };
206-
deserializer.deserialize_any(visitor)
207-
}

0 commit comments

Comments
 (0)