chuanyue-service/domain/src/entities/account.rs
2024-11-02 19:45:19 +08:00

247 lines
6.4 KiB
Rust

use std::fmt::Display;
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use sqlx::types::{chrono, JsonValue};
use sqlx::{Error, PgPool, Postgres, Transaction};
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
pub enum Role {
Admin,
User,
}
impl Role {
pub fn is_admin(&self) -> bool {
match self {
Role::Admin => true,
Role::User => false,
}
}
pub fn is_user(&self) -> bool {
match self {
Role::Admin => false,
Role::User => true,
}
}
}
impl Default for Role {
fn default() -> Self {
Role::User
}
}
impl Display for Role {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Role::Admin => write!(f, "admin"),
Role::User => write!(f, "user"),
}
}
}
impl Into<Role> for String {
fn into(self) -> Role {
match self.as_str() {
"admin" => Role::Admin,
"user" => Role::User,
_ => Role::User,
}
}
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct Account {
pub id: String,
pub username: String,
pub display_name: Option<String>,
pub avatar_url: Option<String>,
pub lang_tag: String,
pub location: Option<String>,
pub timezone: Option<String>,
pub metadata: JsonValue,
pub wallet: JsonValue,
pub email: Option<String>,
pub password: Option<Vec<u8>>,
pub role: Role,
pub facebook_id: Option<String>,
pub google_id: Option<String>,
pub gamecenter_id: Option<String>,
pub steam_id: Option<String>,
pub custom_id: Option<String>,
pub apple_id: Option<String>,
pub facebook_instant_game_id: Option<String>,
pub weixin_id: Option<String>,
pub douyin_id: Option<String>,
pub create_time: DateTime<Utc>,
pub update_time: Option<DateTime<Utc>>,
pub verify_time: Option<DateTime<Utc>>,
pub disable_time: Option<DateTime<Utc>>,
}
impl Account {
pub async fn find_by_apple_id(
apple_id: &str,
db_pool: &PgPool,
) -> Result<Option<Account>, Error> {
match sqlx::query_as!(
Account,
r#"select * from account where apple_id = $1"#,
apple_id
)
.fetch_one(db_pool)
.await
{
Ok(account) => Ok(Some(account)),
Err(Error::RowNotFound) => Ok(None),
Err(e) => {
tracing::error!("find_by_apple_id error: {:?}", e);
Err(e)
}
}
}
pub async fn find_by_custom_id(
custom_id: &str,
db_pool: &PgPool,
) -> Result<Option<Account>, Error> {
match sqlx::query_as!(
Account,
r#"select * from account where custom_id = $1"#,
custom_id
)
.fetch_one(db_pool)
.await
{
Ok(account) => Ok(Some(account)),
Err(Error::RowNotFound) => Ok(None),
Err(e) => {
tracing::error!("find_by_custom_id error: {:?}", e);
Err(e)
}
}
}
pub async fn find_by_facebook_id(
facebook_id: &str,
db_pool: &PgPool,
) -> Result<Option<Account>, Error> {
match sqlx::query_as!(
Account,
r#"select * from account where facebook_id = $1"#,
facebook_id
)
.fetch_one(db_pool)
.await
{
Ok(account) => Ok(Some(account)),
Err(Error::RowNotFound) => Ok(None),
Err(e) => {
tracing::error!("find_by_facebook_id error: {:?}", e);
Err(e)
}
}
}
pub async fn find_by_google_id(
google_id: &str,
db_pool: &PgPool,
) -> Result<Option<Account>, Error> {
match sqlx::query_as!(
Account,
r#"select * from account where google_id = $1"#,
google_id
)
.fetch_one(db_pool)
.await
{
Ok(account) => Ok(Some(account)),
Err(Error::RowNotFound) => Ok(None),
Err(e) => {
tracing::error!("find_by_google_id error: {:?}", e);
Err(e)
}
}
}
pub async fn save_google_account(
&self,
transaction: &mut Transaction<'_, Postgres>,
) -> Result<Account, Error> {
sqlx::query_as!(
Account,
r#"
insert into account
(username, google_id, email, display_name, avatar_url)
values
($1, $2, $3, $4, $5) returning *
"#,
self.username,
self.google_id.as_ref().unwrap(),
self.email.as_ref().unwrap(),
self.display_name.as_ref().unwrap(),
self.avatar_url.as_ref().unwrap()
)
.fetch_one(&mut **transaction)
.await
}
pub async fn find_with_password(
username: String,
password: String,
db_pool: &PgPool,
) -> Result<Option<Account>, Error> {
match sqlx::query_as!(
Account,
r#"
select * from account where username = $1 and password = $2
"#,
username,
password.as_bytes().to_vec(),
)
.fetch_one(db_pool)
.await
{
Ok(account) => Ok(Some(account)),
Err(Error::RowNotFound) => Ok(None),
Err(e) => {
tracing::error!("find_by_google_id error: {:?}", e);
Err(e)
}
}
}
pub async fn add_account(
&self,
transaction: &mut Transaction<'_, Postgres>,
) -> Result<Option<Account>, Error> {
match sqlx::query_as!(
Account,
r#"
insert into account
(username, password, lang_tag, role, wallet, metadata)
values
($1, $2, $3, $4, $5, $6) returning *
"#,
self.username,
self.password,
self.lang_tag,
self.role.to_string(),
self.wallet,
self.metadata
)
.fetch_one(&mut **transaction)
.await
{
Ok(account) => Ok(Some(account)),
Err(Error::RowNotFound) => Ok(None),
Err(e) => {
tracing::error!("add_account error: {:?}", e);
Err(e)
}
}
}
}