mirror of
https://github.com/Xevion/Pac-Man.git
synced 2025-12-07 18:07:42 -06:00
127 lines
3.6 KiB
Rust
127 lines
3.6 KiB
Rust
use serde::Serialize;
|
|
use sqlx::FromRow;
|
|
|
|
#[derive(Debug, Clone, Serialize, FromRow)]
|
|
pub struct User {
|
|
pub id: i64,
|
|
pub email: Option<String>,
|
|
pub created_at: chrono::DateTime<chrono::Utc>,
|
|
pub updated_at: chrono::DateTime<chrono::Utc>,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize, FromRow)]
|
|
pub struct OAuthAccount {
|
|
pub id: i64,
|
|
pub user_id: i64,
|
|
pub provider: String,
|
|
pub provider_user_id: String,
|
|
pub email: Option<String>,
|
|
pub username: Option<String>,
|
|
pub display_name: Option<String>,
|
|
pub avatar_url: Option<String>,
|
|
pub created_at: chrono::DateTime<chrono::Utc>,
|
|
pub updated_at: chrono::DateTime<chrono::Utc>,
|
|
}
|
|
|
|
pub async fn find_user_by_email(pool: &sqlx::PgPool, email: &str) -> Result<Option<User>, sqlx::Error> {
|
|
sqlx::query_as::<_, User>(
|
|
r#"
|
|
SELECT id, email, created_at, updated_at
|
|
FROM users WHERE email = $1
|
|
"#,
|
|
)
|
|
.bind(email)
|
|
.fetch_optional(pool)
|
|
.await
|
|
}
|
|
|
|
#[allow(clippy::too_many_arguments)]
|
|
pub async fn link_oauth_account(
|
|
pool: &sqlx::PgPool,
|
|
user_id: i64,
|
|
provider: &str,
|
|
provider_user_id: &str,
|
|
email: Option<&str>,
|
|
username: Option<&str>,
|
|
display_name: Option<&str>,
|
|
avatar_url: Option<&str>,
|
|
) -> Result<OAuthAccount, sqlx::Error> {
|
|
sqlx::query_as::<_, OAuthAccount>(
|
|
r#"
|
|
INSERT INTO oauth_accounts (user_id, provider, provider_user_id, email, username, display_name, avatar_url)
|
|
VALUES ($1, $2, $3, $4, $5, $6, $7)
|
|
ON CONFLICT (provider, provider_user_id)
|
|
DO UPDATE SET email = EXCLUDED.email, username = EXCLUDED.username, display_name = EXCLUDED.display_name, avatar_url = EXCLUDED.avatar_url, user_id = EXCLUDED.user_id, updated_at = NOW()
|
|
RETURNING id, user_id, provider, provider_user_id, email, username, display_name, avatar_url, created_at, updated_at
|
|
"#,
|
|
)
|
|
.bind(user_id)
|
|
.bind(provider)
|
|
.bind(provider_user_id)
|
|
.bind(email)
|
|
.bind(username)
|
|
.bind(display_name)
|
|
.bind(avatar_url)
|
|
.fetch_one(pool)
|
|
.await
|
|
}
|
|
|
|
pub async fn create_user(pool: &sqlx::PgPool, email: Option<&str>) -> Result<User, sqlx::Error> {
|
|
sqlx::query_as::<_, User>(
|
|
r#"
|
|
INSERT INTO users (email)
|
|
VALUES ($1)
|
|
ON CONFLICT (email) DO UPDATE SET email = EXCLUDED.email
|
|
RETURNING id, email, created_at, updated_at
|
|
"#,
|
|
)
|
|
.bind(email)
|
|
.fetch_one(pool)
|
|
.await
|
|
}
|
|
|
|
pub async fn find_user_by_provider_id(
|
|
pool: &sqlx::PgPool,
|
|
provider: &str,
|
|
provider_user_id: &str,
|
|
) -> Result<Option<User>, sqlx::Error> {
|
|
let rec = sqlx::query_as::<_, User>(
|
|
r#"
|
|
SELECT u.id, u.email, u.created_at, u.updated_at
|
|
FROM users u
|
|
JOIN oauth_accounts oa ON oa.user_id = u.id
|
|
WHERE oa.provider = $1 AND oa.provider_user_id = $2
|
|
"#,
|
|
)
|
|
.bind(provider)
|
|
.bind(provider_user_id)
|
|
.fetch_optional(pool)
|
|
.await?;
|
|
Ok(rec)
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize, FromRow)]
|
|
pub struct ProviderPublic {
|
|
pub provider: String,
|
|
pub provider_user_id: String,
|
|
pub email: Option<String>,
|
|
pub username: Option<String>,
|
|
pub display_name: Option<String>,
|
|
pub avatar_url: Option<String>,
|
|
}
|
|
|
|
pub async fn list_user_providers(pool: &sqlx::PgPool, user_id: i64) -> Result<Vec<ProviderPublic>, sqlx::Error> {
|
|
let recs = sqlx::query_as::<_, ProviderPublic>(
|
|
r#"
|
|
SELECT provider, provider_user_id, email, username, display_name, avatar_url
|
|
FROM oauth_accounts
|
|
WHERE user_id = $1
|
|
ORDER BY provider
|
|
"#,
|
|
)
|
|
.bind(user_id)
|
|
.fetch_all(pool)
|
|
.await?;
|
|
Ok(recs)
|
|
}
|