Merge branch 'main' into feat/admin-api

# Conflicts:
#	crates/core/database/src/drivers/mod.rs
#	crates/core/database/src/drivers/reference.rs
#	crates/core/database/src/models/admin_migrations/ops/mongodb/init.rs
#	crates/core/database/src/models/channels/ops.rs
#	crates/core/database/src/models/server_members/ops.rs
#	crates/core/database/src/models/server_members/ops/mongodb.rs
#	crates/core/database/src/models/server_members/ops/reference.rs
#	crates/core/database/src/util/bridge/v0.rs
#	crates/core/result/src/axum.rs
#	crates/core/result/src/lib.rs
#	crates/core/result/src/rocket.rs
#	crates/delta/src/routes/mod.rs
#	crates/delta/src/routes/servers/server_edit.rs
This commit is contained in:
İspik
2026-06-28 16:08:48 +03:00
186 changed files with 109763 additions and 2624 deletions

View File

@@ -41,6 +41,7 @@ iso8601-timestamp = { workspace = true, features = ["schema", "bson"] }
# Spec Generation
schemars = { workspace = true, features = ["indexmap2"], optional = true }
utoipa = { workspace = true, optional = true }
serde_json = { workspace = true }
# Validation
validator = { workspace = true, features = ["derive"], optional = true }

View File

@@ -0,0 +1,70 @@
auto_derived!(
/// # Change Email Data
pub struct DataChangeEmail {
/// Valid email address
pub email: String,
/// Current password
pub current_password: String,
}
/// # Change Data
pub struct DataChangePassword {
/// New password
pub password: String,
/// Current password
pub current_password: String,
}
/// # Account Deletion Token
pub struct DataAccountDeletion {
/// Deletion token
pub token: String,
}
/// # Account Data
pub struct DataCreateAccount {
/// Valid email address
pub email: String,
/// Password
pub password: String,
/// Invite code
pub invite: Option<String>,
/// Captcha verification code
pub captcha: Option<String>,
}
pub struct AccountInfo {
#[serde(rename = "_id")]
pub id: String,
pub email: String,
}
/// # Password Reset
pub struct DataPasswordReset {
/// Reset token
pub token: String,
/// New password
pub password: String,
/// Whether to logout all sessions
#[serde(default)]
pub remove_sessions: bool,
}
/// # Resend Information
pub struct DataResendVerification {
/// Email associated with the account
pub email: String,
/// Captcha verification code
pub captcha: Option<String>,
}
/// # Reset Information
pub struct DataSendPasswordReset {
/// Email associated with the account
pub email: String,
/// Captcha verification code
pub captcha: Option<String>,
}
);

View File

@@ -0,0 +1,68 @@
auto_derived!(
pub struct MFATicket {
/// Unique Id
#[serde(rename = "_id")]
pub id: String,
/// Account Id
pub account_id: String,
/// Unique Token
pub token: String,
/// Whether this ticket has been validated
/// (can be used for account actions)
pub validated: bool,
/// Whether this ticket is authorised
/// (can be used to log a user in)
pub authorised: bool,
/// TOTP code at time of ticket creation
pub last_totp_code: Option<String>,
}
#[serde(untagged)]
pub enum ResponseVerify {
NoTicket,
WithTicket {
/// Authorised MFA ticket, can be used to log in
ticket: MFATicket,
},
}
/// MFA response
#[serde(untagged)]
pub enum MFAResponse {
Password { password: String },
Recovery { recovery_code: String },
Totp { totp_code: String },
}
#[derive(Default)]
pub struct MultiFactorStatus {
#[serde(skip_serializing_if = "crate::if_false", default)]
pub email_otp: bool,
#[serde(skip_serializing_if = "crate::if_false", default)]
pub trusted_handover: bool,
#[serde(skip_serializing_if = "crate::if_false", default)]
pub email_mfa: bool,
#[serde(skip_serializing_if = "crate::if_false", default)]
pub totp_mfa: bool,
#[serde(skip_serializing_if = "crate::if_false", default)]
pub security_key_mfa: bool,
#[serde(skip_serializing_if = "crate::if_false", default)]
pub recovery_active: bool,
}
pub enum MFAMethod {
Password,
Recovery,
Totp,
}
/// # Totp Secret
pub struct ResponseTotpSecret {
pub secret: String,
}
);

View File

@@ -15,6 +15,9 @@ mod server_members;
mod servers;
mod user_settings;
mod users;
mod accounts;
mod mfa_tickets;
mod sessions;
pub use admin::*;
pub use bots::*;
@@ -33,3 +36,6 @@ pub use server_members::*;
pub use servers::*;
pub use user_settings::*;
pub use users::*;
pub use accounts::*;
pub use mfa_tickets::*;
pub use sessions::*;

View File

@@ -52,6 +52,9 @@ auto_derived_partial!(
/// Member's nickname
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
pub nickname: Option<String>,
/// Member's pronouns
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
pub pronouns: Option<String>,
/// Avatar attachment
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
pub avatar: Option<File>,
@@ -89,6 +92,7 @@ auto_derived!(
/// Optional fields on server member object
pub enum FieldsMember {
Nickname,
Pronouns,
Avatar,
Roles,
Timeout,
@@ -136,6 +140,9 @@ auto_derived!(
/// Member nickname
#[cfg_attr(feature = "validator", validate(length(min = 1, max = 32)))]
pub nickname: Option<String>,
/// Member pronouns
#[cfg_attr(feature = "validator", validate(length(min = 1, max = 24)))]
pub pronouns: Option<String>,
/// Attachment Id to set for avatar
pub avatar: Option<String>,
/// Array of role ids

View File

@@ -0,0 +1,88 @@
use iso8601_timestamp::Timestamp;
use crate::v0::{MFAMethod, MFAResponse};
auto_derived!(
pub struct Session {
/// Unique Id
#[serde(rename = "_id")]
pub id: String,
/// User Id
pub user_id: String,
/// Session token
pub token: String,
/// Display name
pub name: String,
/// When the session was last logged in
pub last_seen: Timestamp,
/// Where the session is originating from
#[serde(skip_serializing_if = "Option::is_none")]
pub origin: Option<String>,
/// Web Push subscription
#[serde(skip_serializing_if = "Option::is_none")]
pub subscription: Option<WebPushSubscription>,
}
/// Web Push subscription
pub struct WebPushSubscription {
pub endpoint: String,
pub p256dh: String,
pub auth: String,
}
/// # Edit Data
pub struct DataEditSession {
/// Session friendly name
pub friendly_name: String,
}
pub struct SessionInfo {
#[serde(rename = "_id")]
pub id: String,
pub name: String,
}
/// # Login Data
#[serde(untagged)]
pub enum DataLogin {
Email {
/// Email
email: String,
/// Password
password: String,
/// Friendly name used for the session
friendly_name: Option<String>,
},
MFA {
/// Unvalidated or authorised MFA ticket
///
/// Used to resolve the correct account
mfa_ticket: String,
/// Valid MFA response
///
/// This will take precedence over the `password` field where applicable
mfa_response: Option<MFAResponse>,
/// Friendly name used for the session
friendly_name: Option<String>,
},
}
#[serde(tag = "result")]
pub enum ResponseLogin {
Success(Session),
MFA {
ticket: String,
allowed_methods: Vec<MFAMethod>,
},
Disabled {
user_id: String,
},
}
);

View File

@@ -32,6 +32,9 @@ auto_derived_partial!(
/// Display name
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
pub display_name: Option<String>,
/// User's pronouns
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
pub pronouns: Option<String>,
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
/// Avatar attachment
pub avatar: Option<File>,
@@ -89,6 +92,7 @@ auto_derived!(
ProfileContent,
ProfileBackground,
DisplayName,
Pronouns,
/// Internal field, ignore this.
Internal,
@@ -227,6 +231,9 @@ auto_derived!(
validate(length(min = 2, max = 32), regex = "RE_DISPLAY_NAME")
)]
pub display_name: Option<String>,
/// New pronouns
#[cfg_attr(feature = "validator", validate(length(min = 1, max = 24)))]
pub pronouns: Option<String>,
/// Attachment Id for avatar
#[cfg_attr(feature = "validator", validate(length(min = 1, max = 128)))]
pub avatar: Option<String>,