diff --git a/src/handlers/accounts.rs b/src/handlers/accounts.rs index cdbcf24..deb99d9 100644 --- a/src/handlers/accounts.rs +++ b/src/handlers/accounts.rs @@ -13,6 +13,7 @@ use crate::{ error::AppError, models::{ cipher::CipherData, + sync::Profile, user::{ ChangePasswordRequest, DeleteAccountRequest, PreloginResponse, RegisterRequest, RotateKeyRequest, User, @@ -180,6 +181,26 @@ pub async fn revision_date( Ok(Json(revision_date)) } +#[worker::send] +pub async fn get_profile( + claims: Claims, + State(env): State>, +) -> Result, AppError> { + let db = db::get_db(&env)?; + let user_id = claims.sub; + + let user: User = db + .prepare("SELECT * FROM users WHERE id = ?1") + .bind(&[user_id.into()])? + .first(None) + .await? + .ok_or_else(|| AppError::NotFound("User not found".to_string()))?; + + let profile = Profile::from_user(user)?; + + Ok(Json(profile)) +} + #[worker::send] pub async fn delete_account( claims: Claims, diff --git a/src/handlers/sync.rs b/src/handlers/sync.rs index 61db182..9f3912a 100644 --- a/src/handlers/sync.rs +++ b/src/handlers/sync.rs @@ -63,26 +63,7 @@ pub async fn get_sync_data( .map(|cipher| cipher.into()) .collect::>(); - let time = chrono::DateTime::parse_from_rfc3339(&user.created_at) - .map_err(|_| AppError::Internal)? - .to_rfc3339_opts(chrono::SecondsFormat::Micros, true); - let profile = Profile { - id: user.id, - name: user.name, - email: user.email, - master_password_hint: user.master_password_hint, - security_stamp: user.security_stamp, - object: "profile".to_string(), - premium: true, - premium_from_organization: false, - email_verified: true, - force_password_reset: false, - two_factor_enabled: false, - uses_key_connector: false, - creation_date: time, - key: user.key, - private_key: user.private_key, - }; + let profile = Profile::from_user(user)?; let response = SyncResponse { profile, diff --git a/src/models/sync.rs b/src/models/sync.rs index eedc5c7..16dc89e 100644 --- a/src/models/sync.rs +++ b/src/models/sync.rs @@ -1,4 +1,6 @@ -use super::{cipher::Cipher, folder::FolderResponse}; +use super::{cipher::Cipher, folder::FolderResponse, user::User}; +use crate::error::AppError; +use chrono::SecondsFormat; use serde::Serialize; use serde_json::Value; @@ -24,6 +26,32 @@ pub struct Profile { pub key: String, } +impl Profile { + pub fn from_user(user: User) -> Result { + let creation_date = chrono::DateTime::parse_from_rfc3339(&user.created_at) + .map_err(|_| AppError::Internal)? + .to_rfc3339_opts(SecondsFormat::Micros, true); + + Ok(Self { + id: user.id, + name: user.name, + email: user.email, + master_password_hint: user.master_password_hint, + security_stamp: user.security_stamp, + object: "profile".to_string(), + premium_from_organization: false, + force_password_reset: false, + email_verified: true, + two_factor_enabled: false, + premium: true, + uses_key_connector: false, + creation_date, + private_key: user.private_key, + key: user.key, + }) + } +} + #[derive(Debug, Serialize)] #[serde(rename_all = "camelCase")] pub struct SyncResponse { diff --git a/src/router.rs b/src/router.rs index 75f4874..cf85ef6 100644 --- a/src/router.rs +++ b/src/router.rs @@ -26,6 +26,7 @@ pub fn api_router(env: Env) -> Router { .route("/api/sync", get(sync::get_sync_data)) // For on-demand sync checks .route("/api/accounts/revision-date", get(accounts::revision_date)) + .route("/api/accounts/profile", get(accounts::get_profile)) // Delete account .route("/api/accounts", delete(accounts::delete_account)) .route("/api/accounts/delete", post(accounts::delete_account))