feat: add profile retrieval endpoint and refactor profile creation logic

This commit is contained in:
qaz741wsd856 2025-12-04 03:26:30 +00:00
parent 8b22bf9fc1
commit 238573f299
4 changed files with 52 additions and 21 deletions

View file

@ -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<Arc<Env>>,
) -> Result<Json<Profile>, 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,

View file

@ -63,26 +63,7 @@ pub async fn get_sync_data(
.map(|cipher| cipher.into())
.collect::<Vec<Cipher>>();
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,

View file

@ -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<Self, AppError> {
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 {

View file

@ -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))