#[cfg(feature="sea-orm")]
use sea_orm::entity::prelude::*;
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature="sea-orm",derive( DeriveEntityModel))]
#[cfg_attr(feature="serde",derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature="sea-orm",sea_orm(table_name = "user_accounts"))]
pub struct Model {
#[cfg_attr(feature="sea-orm",sea_orm(primary_key))]
pub id: i64,
pub user_id: i64,
#[cfg_attr(feature="sea-orm",sea_orm(column_type = "Text", unique))]
pub external_user_id: String,
}
#[cfg(feature="sea-orm")]
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {
#[sea_orm(
belongs_to = "super::user::Entity",
from = "Column::UserId",
to = "super::user::Column::Id",
on_update = "NoAction",
on_delete = "NoAction"
)]
User2,
#[sea_orm(
belongs_to = "super::user::Entity",
from = "Column::UserId",
to = "super::user::Column::Id",
on_update = "NoAction",
on_delete = "NoAction"
)]
User1,
}
#[cfg(feature="sea-orm")]
impl ActiveModelBehavior for ActiveModel {}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature="clap",derive(clap::Args))]
#[cfg_attr(feature="serde",derive(serde::Serialize, serde::Deserialize))]
pub struct CreateUserAccountOptions {
#[cfg_attr(feature="clap",arg(short,long))]
pub user_id: i64,
#[cfg_attr(feature="clap",arg(short,long))]
pub external_user_id: String,
#[cfg_attr(feature="clap",arg(short,long))]
pub id: Option<i64>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature="clap",derive(clap::Args))]
#[cfg_attr(feature="serde",derive(serde::Serialize, serde::Deserialize))]
pub struct LinkAccountToUserOptions {
#[cfg_attr(feature="clap",arg(short,long))]
pub user_id: i64,
#[cfg_attr(feature="clap",arg(short,long))]
pub external_user_id: String,
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature="serde",derive(serde::Serialize, serde::Deserialize))]
pub struct UserAndAccount {
pub user: crate::user::Model,
pub account: Model
}
#[cfg(feature="sea-orm")]
pub async fn create(conn: &sea_orm::DatabaseConnection,opts: &CreateUserAccountOptions) -> Result<Model,anyhow::Error> {
let user = super::user::get_by_id(conn, opts.user_id).await.map_err(|e| e.context("While verifying that the user exists in the database"))?.ok_or_else(|| anyhow::anyhow!("There is no user with an id of {}",opts.user_id))?;
let mut active_model: ActiveModel = <ActiveModel as ActiveModelTrait>::default();
active_model.user_id = sea_orm::ActiveValue::Set(user.id);
active_model.external_user_id = sea_orm::ActiveValue::Set(opts.external_user_id.clone());
if opts.id.is_some() {
active_model.id = sea_orm::ActiveValue::set(opts.id.unwrap())
}
let model: Model = active_model.save(conn).await?.try_into()?;
Ok(model)
}
#[cfg(feature="sea-orm")]
pub async fn get_account_by_external_id(conn:&sea_orm::DatabaseConnection,external_user_id: &str) -> Result<Option<Model>,anyhow::Error> {
Entity::find().filter(Column::ExternalUserId.eq(external_user_id.to_string())).one(conn).await.map_err(|e| anyhow::Error::new(e).context("While getting a user account by external id"))
}
#[cfg(feature="sea-orm")]
pub async fn link_account_to_user(conn: &sea_orm::DatabaseConnection,options: &LinkAccountToUserOptions) -> Result<UserAndAccount,anyhow::Error> {
let user = crate::user::get_by_id(&conn, options.user_id).await.map_err(|e| e.context("While trying to find a user to link to a user_account"))?
.ok_or_else(||anyhow::anyhow!("Could not find a user with an id of {0} while trying to connect a user to an account",options.user_id))?;
let account = get_account_by_external_id(conn,&options.external_user_id).await.map_err(|e| e.context("While linking a user_account to a user"))?.ok_or_else( ||anyhow::anyhow!("There is no account with an external id of '{}'",options.external_user_id))?;
let mut active_model =ActiveModel::from(account.clone());
active_model.user_id = sea_orm::ActiveValue::Set(user.id);
let _ =active_model.save(conn).await.map_err(|e| anyhow::Error::new(e).context("Failed to link user account"))?;
Ok(UserAndAccount{user,account})
}