use crate::{auth::AuthProvider, bitflags_serde_impl}; pub use ariadne::users::{UserId, UserStatus}; use chrono::{DateTime, Utc}; use rust_decimal::Decimal; use serde::{Deserialize, Serialize}; pub const DELETED_USER: UserId = UserId(127155982985829); bitflags::bitflags! { #[derive(Copy, Clone, Debug)] pub struct Badges: u64 { const MIDAS = 1 << 0; const EARLY_MODPACK_ADOPTER = 1 << 1; const EARLY_RESPACK_ADOPTER = 1 << 2; const EARLY_PLUGIN_ADOPTER = 1 << 3; const ALPHA_TESTER = 1 << 4; const CONTRIBUTOR = 1 << 5; const TRANSLATOR = 1 << 6; const ALL = 0b1111111; const NONE = 0b0; } } bitflags_serde_impl!(Badges, u64); impl Default for Badges { fn default() -> Badges { Badges::NONE } } #[derive(Serialize, Deserialize, Clone, Debug)] pub struct User { pub id: UserId, pub username: String, pub avatar_url: Option, pub bio: Option, pub created: DateTime, pub role: Role, pub badges: Badges, pub auth_providers: Option>, pub email: Option, pub email_verified: Option, pub has_password: Option, pub has_totp: Option, pub payout_data: Option, pub stripe_customer_id: Option, pub allow_friend_requests: Option, // DEPRECATED. Always returns None pub github_id: Option, } #[derive(Serialize, Deserialize, Clone, Debug)] pub struct UserPayoutData { pub paypal_address: Option, pub paypal_country: Option, pub venmo_handle: Option, #[serde(with = "rust_decimal::serde::float")] pub balance: Decimal, } use crate::database::models::user_item::User as DBUser; impl From for User { fn from(data: DBUser) -> Self { Self { id: data.id.into(), username: data.username, email: None, email_verified: None, avatar_url: data.avatar_url, bio: data.bio, created: data.created, role: Role::from_string(&data.role), badges: data.badges, payout_data: None, auth_providers: None, has_password: None, has_totp: None, github_id: None, stripe_customer_id: None, allow_friend_requests: None, } } } impl User { pub fn from_full(db_user: DBUser) -> Self { let mut auth_providers = Vec::new(); if db_user.github_id.is_some() { auth_providers.push(AuthProvider::GitHub) } if db_user.gitlab_id.is_some() { auth_providers.push(AuthProvider::GitLab) } if db_user.discord_id.is_some() { auth_providers.push(AuthProvider::Discord) } if db_user.google_id.is_some() { auth_providers.push(AuthProvider::Google) } if db_user.microsoft_id.is_some() { auth_providers.push(AuthProvider::Microsoft) } if db_user.steam_id.is_some() { auth_providers.push(AuthProvider::Steam) } if db_user.paypal_id.is_some() { auth_providers.push(AuthProvider::PayPal) } Self { id: UserId::from(db_user.id), username: db_user.username, email: db_user.email, email_verified: Some(db_user.email_verified), avatar_url: db_user.avatar_url, bio: db_user.bio, created: db_user.created, role: Role::from_string(&db_user.role), badges: db_user.badges, auth_providers: Some(auth_providers), has_password: Some(db_user.password.is_some()), has_totp: Some(db_user.totp_secret.is_some()), github_id: None, payout_data: Some(UserPayoutData { paypal_address: db_user.paypal_email, paypal_country: db_user.paypal_country, venmo_handle: db_user.venmo_handle, balance: Decimal::ZERO, }), stripe_customer_id: db_user.stripe_customer_id, allow_friend_requests: Some(db_user.allow_friend_requests), } } } #[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Debug)] #[serde(rename_all = "lowercase")] pub enum Role { Developer, Moderator, Admin, } impl std::fmt::Display for Role { fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { fmt.write_str(self.as_str()) } } impl Role { pub fn from_string(string: &str) -> Role { match string { "admin" => Role::Admin, "moderator" => Role::Moderator, _ => Role::Developer, } } pub fn as_str(&self) -> &'static str { match self { Role::Developer => "developer", Role::Moderator => "moderator", Role::Admin => "admin", } } pub fn is_mod(&self) -> bool { match self { Role::Developer => false, Role::Moderator | Role::Admin => true, } } pub fn is_admin(&self) -> bool { match self { Role::Developer | Role::Moderator => false, Role::Admin => true, } } } #[derive(Serialize, Deserialize)] pub struct UserFriend { // The user who accepted the friend request pub id: UserId, /// THe user who sent the friend request pub friend_id: UserId, pub accepted: bool, pub created: DateTime, } impl UserFriend { pub fn from( data: crate::database::models::friend_item::FriendItem, ) -> Self { Self { id: data.friend_id.into(), friend_id: data.user_id.into(), accepted: data.accepted, created: data.created, } } }