Phase 2.2: MongoDB connection and models
This commit is contained in:
parent
1cf927f527
commit
154c3d1152
13 changed files with 544 additions and 5 deletions
31
backend/src/models/appointment.rs
Normal file
31
backend/src/models/appointment.rs
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
use mongodb::bson::{oid::ObjectId, DateTime};
|
||||
use super::health_data::EncryptedField;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct Appointment {
|
||||
#[serde(rename = "_id", skip_serializing_if = "Option::is_none")]
|
||||
pub id: Option<ObjectId>,
|
||||
#[serde(rename = "appointmentId")]
|
||||
pub appointment_id: String,
|
||||
#[serde(rename = "userId")]
|
||||
pub user_id: String,
|
||||
#[serde(rename = "profileId")]
|
||||
pub profile_id: String,
|
||||
#[serde(rename = "appointmentData")]
|
||||
pub appointment_data: EncryptedField,
|
||||
#[serde(rename = "reminders")]
|
||||
pub reminders: Vec<AppointmentReminder>,
|
||||
#[serde(rename = "createdAt")]
|
||||
pub created_at: DateTime,
|
||||
#[serde(rename = "updatedAt")]
|
||||
pub updated_at: DateTime,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct AppointmentReminder {
|
||||
#[serde(rename = "reminderId")]
|
||||
pub reminder_id: String,
|
||||
#[serde(rename = "scheduledTime")]
|
||||
pub scheduled_time: String,
|
||||
}
|
||||
43
backend/src/models/family.rs
Normal file
43
backend/src/models/family.rs
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
use mongodb::{bson::{doc, oid::ObjectId, DateTime}, Collection};
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct Family {
|
||||
#[serde(rename = "_id", skip_serializing_if = "Option::is_none")]
|
||||
pub id: Option<ObjectId>,
|
||||
#[serde(rename = "familyId")]
|
||||
pub family_id: String,
|
||||
#[serde(rename = "name")]
|
||||
pub name: String,
|
||||
#[serde(rename = "nameIv")]
|
||||
pub name_iv: String,
|
||||
#[serde(rename = "nameAuthTag")]
|
||||
pub name_auth_tag: String,
|
||||
#[serde(rename = "memberIds")]
|
||||
pub member_ids: Vec<String>,
|
||||
#[serde(rename = "createdAt")]
|
||||
pub created_at: DateTime,
|
||||
#[serde(rename = "updatedAt")]
|
||||
pub updated_at: DateTime,
|
||||
}
|
||||
|
||||
pub struct FamilyRepository {
|
||||
collection: Collection<Family>,
|
||||
}
|
||||
|
||||
impl FamilyRepository {
|
||||
pub fn new(collection: Collection<Family>) -> Self {
|
||||
Self { collection }
|
||||
}
|
||||
|
||||
pub async fn create(&self, family: &Family) -> mongodb::error::Result<()> {
|
||||
self.collection.insert_one(family, None).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn find_by_family_id(&self, family_id: &str) -> mongodb::error::Result<Option<Family>> {
|
||||
self.collection
|
||||
.find_one(doc! { "familyId": family_id }, None)
|
||||
.await
|
||||
}
|
||||
}
|
||||
32
backend/src/models/health_data.rs
Normal file
32
backend/src/models/health_data.rs
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
use mongodb::bson::{oid::ObjectId, DateTime};
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct HealthData {
|
||||
#[serde(rename = "_id", skip_serializing_if = "Option::is_none")]
|
||||
pub id: Option<ObjectId>,
|
||||
#[serde(rename = "healthDataId")]
|
||||
pub health_data_id: String,
|
||||
#[serde(rename = "userId")]
|
||||
pub user_id: String,
|
||||
#[serde(rename = "profileId")]
|
||||
pub profile_id: String,
|
||||
#[serde(rename = "familyId")]
|
||||
pub family_id: Option<String>,
|
||||
#[serde(rename = "healthData")]
|
||||
pub health_data: Vec<EncryptedField>,
|
||||
#[serde(rename = "createdAt")]
|
||||
pub created_at: DateTime,
|
||||
#[serde(rename = "updatedAt")]
|
||||
pub updated_at: DateTime,
|
||||
#[serde(rename = "dataSource")]
|
||||
pub data_source: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct EncryptedField {
|
||||
pub encrypted: bool,
|
||||
pub data: String,
|
||||
pub iv: String,
|
||||
pub auth_tag: String,
|
||||
}
|
||||
21
backend/src/models/lab_result.rs
Normal file
21
backend/src/models/lab_result.rs
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
use mongodb::bson::{oid::ObjectId, DateTime};
|
||||
use super::health_data::EncryptedField;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct LabResult {
|
||||
#[serde(rename = "_id", skip_serializing_if = "Option::is_none")]
|
||||
pub id: Option<ObjectId>,
|
||||
#[serde(rename = "labResultId")]
|
||||
pub lab_result_id: String,
|
||||
#[serde(rename = "userId")]
|
||||
pub user_id: String,
|
||||
#[serde(rename = "profileId")]
|
||||
pub profile_id: String,
|
||||
#[serde(rename = "labData")]
|
||||
pub lab_data: EncryptedField,
|
||||
#[serde(rename = "createdAt")]
|
||||
pub created_at: DateTime,
|
||||
#[serde(rename = "updatedAt")]
|
||||
pub updated_at: DateTime,
|
||||
}
|
||||
31
backend/src/models/medication.rs
Normal file
31
backend/src/models/medication.rs
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
use mongodb::bson::{oid::ObjectId, DateTime};
|
||||
use super::health_data::EncryptedField;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct Medication {
|
||||
#[serde(rename = "_id", skip_serializing_if = "Option::is_none")]
|
||||
pub id: Option<ObjectId>,
|
||||
#[serde(rename = "medicationId")]
|
||||
pub medication_id: String,
|
||||
#[serde(rename = "userId")]
|
||||
pub user_id: String,
|
||||
#[serde(rename = "profileId")]
|
||||
pub profile_id: String,
|
||||
#[serde(rename = "medicationData")]
|
||||
pub medication_data: EncryptedField,
|
||||
#[serde(rename = "reminders")]
|
||||
pub reminders: Vec<MedicationReminder>,
|
||||
#[serde(rename = "createdAt")]
|
||||
pub created_at: DateTime,
|
||||
#[serde(rename = "updatedAt")]
|
||||
pub updated_at: DateTime,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct MedicationReminder {
|
||||
#[serde(rename = "reminderId")]
|
||||
pub reminder_id: String,
|
||||
#[serde(rename = "scheduledTime")]
|
||||
pub scheduled_time: String,
|
||||
}
|
||||
9
backend/src/models/mod.rs
Normal file
9
backend/src/models/mod.rs
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
pub mod user;
|
||||
pub mod family;
|
||||
pub mod profile;
|
||||
pub mod health_data;
|
||||
pub mod lab_result;
|
||||
pub mod medication;
|
||||
pub mod appointment;
|
||||
pub mod share;
|
||||
pub mod refresh_token;
|
||||
49
backend/src/models/profile.rs
Normal file
49
backend/src/models/profile.rs
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
use mongodb::{bson::{doc, oid::ObjectId, DateTime}, Collection};
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct Profile {
|
||||
#[serde(rename = "_id", skip_serializing_if = "Option::is_none")]
|
||||
pub id: Option<ObjectId>,
|
||||
#[serde(rename = "profileId")]
|
||||
pub profile_id: String,
|
||||
#[serde(rename = "userId")]
|
||||
pub user_id: String,
|
||||
#[serde(rename = "familyId")]
|
||||
pub family_id: Option<String>,
|
||||
#[serde(rename = "name")]
|
||||
pub name: String,
|
||||
#[serde(rename = "nameIv")]
|
||||
pub name_iv: String,
|
||||
#[serde(rename = "nameAuthTag")]
|
||||
pub name_auth_tag: String,
|
||||
#[serde(rename = "role")]
|
||||
pub role: String,
|
||||
#[serde(rename = "permissions")]
|
||||
pub permissions: Vec<String>,
|
||||
#[serde(rename = "createdAt")]
|
||||
pub created_at: DateTime,
|
||||
#[serde(rename = "updatedAt")]
|
||||
pub updated_at: DateTime,
|
||||
}
|
||||
|
||||
pub struct ProfileRepository {
|
||||
collection: Collection<Profile>,
|
||||
}
|
||||
|
||||
impl ProfileRepository {
|
||||
pub fn new(collection: Collection<Profile>) -> Self {
|
||||
Self { collection }
|
||||
}
|
||||
|
||||
pub async fn create(&self, profile: &Profile) -> mongodb::error::Result<()> {
|
||||
self.collection.insert_one(profile, None).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn find_by_profile_id(&self, profile_id: &str) -> mongodb::error::Result<Option<Profile>> {
|
||||
self.collection
|
||||
.find_one(doc! { "profileId": profile_id }, None)
|
||||
.await
|
||||
}
|
||||
}
|
||||
22
backend/src/models/refresh_token.rs
Normal file
22
backend/src/models/refresh_token.rs
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
use mongodb::bson::{oid::ObjectId, DateTime};
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct RefreshToken {
|
||||
#[serde(rename = "_id", skip_serializing_if = "Option::is_none")]
|
||||
pub id: Option<ObjectId>,
|
||||
#[serde(rename = "tokenId")]
|
||||
pub token_id: String,
|
||||
#[serde(rename = "userId")]
|
||||
pub user_id: String,
|
||||
#[serde(rename = "tokenHash")]
|
||||
pub token_hash: String,
|
||||
#[serde(rename = "expiresAt")]
|
||||
pub expires_at: DateTime,
|
||||
#[serde(rename = "createdAt")]
|
||||
pub created_at: DateTime,
|
||||
#[serde(rename = "revoked")]
|
||||
pub revoked: bool,
|
||||
#[serde(rename = "revokedAt")]
|
||||
pub revoked_at: Option<DateTime>,
|
||||
}
|
||||
24
backend/src/models/share.rs
Normal file
24
backend/src/models/share.rs
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
use mongodb::bson::{oid::ObjectId, DateTime};
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct Share {
|
||||
#[serde(rename = "_id", skip_serializing_if = "Option::is_none")]
|
||||
pub id: Option<ObjectId>,
|
||||
#[serde(rename = "shareId")]
|
||||
pub share_id: String,
|
||||
#[serde(rename = "userId")]
|
||||
pub user_id: String,
|
||||
#[serde(rename = "encryptedDataKey")]
|
||||
pub encrypted_data_key: String,
|
||||
#[serde(rename = "dataKeyIv")]
|
||||
pub data_key_iv: String,
|
||||
#[serde(rename = "dataKeyAuthTag")]
|
||||
pub data_key_auth_tag: String,
|
||||
#[serde(rename = "expiresAt")]
|
||||
pub expires_at: DateTime,
|
||||
#[serde(rename = "createdAt")]
|
||||
pub created_at: DateTime,
|
||||
#[serde(rename = "accessCount")]
|
||||
pub access_count: i32,
|
||||
}
|
||||
88
backend/src/models/user.rs
Normal file
88
backend/src/models/user.rs
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
use mongodb::{bson::{doc, oid::ObjectId, DateTime}, Collection};
|
||||
use chrono::{Utc, TimeZone};
|
||||
use validator::Validate;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct User {
|
||||
#[serde(rename = "_id", skip_serializing_if = "Option::is_none")]
|
||||
pub id: Option<ObjectId>,
|
||||
#[serde(rename = "userId")]
|
||||
pub user_id: String,
|
||||
#[serde(rename = "email")]
|
||||
pub email: String,
|
||||
#[serde(rename = "passwordHash")]
|
||||
pub password_hash: String,
|
||||
#[serde(rename = "encryptedRecoveryPhrase")]
|
||||
pub encrypted_recovery_phrase: String,
|
||||
#[serde(rename = "recoveryPhraseIv")]
|
||||
pub recovery_phrase_iv: String,
|
||||
#[serde(rename = "recoveryPhraseAuthTag")]
|
||||
pub recovery_phrase_auth_tag: String,
|
||||
#[serde(rename = "tokenVersion")]
|
||||
pub token_version: i32,
|
||||
#[serde(rename = "familyId")]
|
||||
pub family_id: Option<String>,
|
||||
#[serde(rename = "profileIds")]
|
||||
pub profile_ids: Vec<String>,
|
||||
#[serde(rename = "createdAt")]
|
||||
pub created_at: DateTime,
|
||||
#[serde(rename = "updatedAt")]
|
||||
pub updated_at: DateTime,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Validate)]
|
||||
pub struct RegisterUserRequest {
|
||||
#[validate(email)]
|
||||
pub email: String,
|
||||
pub password_hash: String,
|
||||
pub encrypted_recovery_phrase: String,
|
||||
pub recovery_phrase_iv: String,
|
||||
pub recovery_phrase_auth_tag: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Validate)]
|
||||
pub struct LoginRequest {
|
||||
#[validate(email)]
|
||||
pub email: String,
|
||||
pub password_hash: String,
|
||||
}
|
||||
|
||||
pub struct UserRepository {
|
||||
collection: Collection<User>,
|
||||
}
|
||||
|
||||
impl UserRepository {
|
||||
pub fn new(collection: Collection<User>) -> Self {
|
||||
Self { collection }
|
||||
}
|
||||
|
||||
pub async fn create(&self, user: &User) -> mongodb::error::Result<()> {
|
||||
self.collection.insert_one(user, None).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn find_by_email(&self, email: &str) -> mongodb::error::Result<Option<User>> {
|
||||
self.collection
|
||||
.find_one(doc! { "email": email }, None)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn find_by_user_id(&self, user_id: &str) -> mongodb::error::Result<Option<User>> {
|
||||
self.collection
|
||||
.find_one(doc! { "userId": user_id }, None)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn update_token_version(&self, user_id: &str, version: i32) -> mongodb::error::Result<()> {
|
||||
let now = DateTime::now();
|
||||
self.collection
|
||||
.update_one(
|
||||
doc! { "userId": user_id },
|
||||
doc! { "$set": { "tokenVersion": version, "updatedAt": now } },
|
||||
None,
|
||||
)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue