use models::users::user::{self, ProfileVisibility}; use models::users::user_emails; use sea_orm::{ActiveModelTrait, ColumnTrait, EntityTrait, QueryFilter, Set}; use time::OffsetDateTime; use crate::errors::AuthError; use crate::services::AuthService; pub async fn upsert( service: &AuthService, public: &kenauth::proto::common::v1::UserPublic, ) -> Result { let db = service.db().write(); let now = OffsetDateTime::now_utc(); let lower = public.username.to_lowercase(); let display_name = if public.displayname.trim().is_empty() { public.username.clone() } else { public.displayname.clone() }; let avatar_url = public.avatar_url.clone(); let existing = user::Entity::find_by_id(public.user_id) .one(db) .await? .or_else(|| None); let row = match existing { Some(row) => { let mut am: user::ActiveModel = row.into(); am.username = Set(public.username.clone()); am.lower_name = Set(lower); am.display_name = Set(display_name); am.avatar_url = Set(avatar_url); am.is_active = Set(true); am.prohibit_login = Set(false); am.updated_at = Set(now); am.update(db).await? } None => { user::ActiveModel { uid: Set(public.user_id), username: Set(public.username.clone()), lower_name: Set(lower), display_name: Set(display_name), avatar_url: Set(avatar_url), is_active: Set(true), is_restricted: Set(false), prohibit_login: Set(false), visibility: Set(ProfileVisibility::Public), bot: Set(false), system: Set(false), last_login_at: Set(None), last_login_ip_hash: Set(None), version: Set(1), passwd_hash: Set(None), password_last_changed_at: Set(None), passwd_version: Set(None), totp_encrypted_secret: Set(None), totp_enabled: Set(false), totp_last_used_at: Set(None), totp_last_counter: Set(None), timezone: Set(None), locale: Set(None), language: Set(None), created_at: Set(now), updated_at: Set(now), } .insert(db) .await? } }; if !public.email.trim().is_empty() { let lower_email = public.email.to_lowercase(); let existing_email = user_emails::Entity::find() .filter(user_emails::Column::UserId.eq(public.user_id)) .filter(user_emails::Column::IsPrimary.eq(true)) .one(db) .await?; match existing_email { Some(email_row) => { let mut am: user_emails::ActiveModel = email_row.into(); am.email = Set(public.email.clone()); am.lower_email = Set(lower_email); am.is_activated = Set(public.email_verified); am.updated_at = Set(now); am.update(db).await?; } None => { user_emails::ActiveModel { id: Set(uuid::Uuid::now_v7()), user_id: Set(public.user_id), email: Set(public.email.clone()), lower_email: Set(lower_email), is_activated: Set(public.email_verified), is_primary: Set(true), created_at: Set(now), updated_at: Set(now), activated_at: Set(public.email_verified.then_some(now)), deleted_at: Set(None), } .insert(db) .await?; } } } Ok(row) }