TOTP google authenticator implemented properly well
This commit is contained in:
@@ -34,6 +34,7 @@ mod m20260618_000001_o_auth2_sessions;
|
||||
mod m20260618_000002_customer_profiles;
|
||||
mod m20260618_000003_account_type;
|
||||
mod m20260618_000004_account_ownership;
|
||||
mod m20260620_000001_add_totp_to_users;
|
||||
pub struct Migrator;
|
||||
|
||||
#[async_trait::async_trait]
|
||||
@@ -72,6 +73,7 @@ impl MigratorTrait for Migrator {
|
||||
Box::new(m20260618_000002_customer_profiles::Migration),
|
||||
Box::new(m20260618_000003_account_type::Migration),
|
||||
Box::new(m20260618_000004_account_ownership::Migration),
|
||||
Box::new(m20260620_000001_add_totp_to_users::Migration),
|
||||
// inject-above (do not remove this comment)
|
||||
]
|
||||
}
|
||||
|
||||
32
migration/src/m20260620_000001_add_totp_to_users.rs
Normal file
32
migration/src/m20260620_000001_add_totp_to_users.rs
Normal file
@@ -0,0 +1,32 @@
|
||||
use loco_rs::schema::*;
|
||||
use sea_orm_migration::prelude::*;
|
||||
|
||||
#[derive(DeriveMigrationName)]
|
||||
pub struct Migration;
|
||||
|
||||
// Optional TOTP (Google Authenticator) two-factor auth. All three columns are
|
||||
// nullable and only populated once a user opts in:
|
||||
// - `totp_secret` base32 shared secret; present while enrolling/enabled.
|
||||
// TODO(security): stored PLAINTEXT and is password-
|
||||
// equivalent (must stay reversible to recompute codes).
|
||||
// Encrypt at rest later with an out-of-DB key. See the
|
||||
// TODO(security) block in src/models/users.rs.
|
||||
// - `totp_enabled_at` NULL = 2FA off. Set only after the user confirms a
|
||||
// code, so a half-finished enrollment never gates login.
|
||||
// - `totp_backup_codes` JSON array of hashed one-time recovery codes.
|
||||
#[async_trait::async_trait]
|
||||
impl MigrationTrait for Migration {
|
||||
async fn up(&self, m: &SchemaManager) -> Result<(), DbErr> {
|
||||
add_column(m, "users", "totp_secret", ColType::TextNull).await?;
|
||||
add_column(m, "users", "totp_enabled_at", ColType::TimestampWithTimeZoneNull).await?;
|
||||
add_column(m, "users", "totp_backup_codes", ColType::TextNull).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn down(&self, m: &SchemaManager) -> Result<(), DbErr> {
|
||||
remove_column(m, "users", "totp_backup_codes").await?;
|
||||
remove_column(m, "users", "totp_enabled_at").await?;
|
||||
remove_column(m, "users", "totp_secret").await?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user