Our Personal Data Server from scratch! tranquil.farm
oauth atproto pds rust postgresql objectstorage fun

feat: legacy 2fa implementation #8

merged opened by lewis.moe targeting main from feat/bsky-2fa-shim

I think it would be nice to have the legacy 2fa available for fun.

Labels

None yet.

assignee

None yet.

Participants 2
Referenced by
AT URI
at://did:plc:3fwecdnvtcscjnrx2p4n7alz/sh.tangled.repo.pull/3mdikn4nj6h22
+274 -528
Interdiff #0 โ†’ #1
-136
.sqlx/query-15333a3aa7fff82a603352d5f1bcff7b36510e86145a5e216948641318cc3229.json
··· 1 - { 2 - "db_name": "PostgreSQL", 3 - "query": "SELECT\n u.id, u.did, u.handle, u.password_hash, u.email, u.deactivated_at, u.takedown_ref,\n u.email_verified, u.discord_verified, u.telegram_verified, u.signal_verified,\n u.allow_legacy_login, u.migrated_to_pds,\n u.preferred_comms_channel as \"preferred_comms_channel: CommsChannel\",\n k.key_bytes, k.encryption_version,\n (SELECT verified FROM user_totp WHERE did = u.did) as totp_enabled,\n COALESCE((SELECT (value_json)::boolean FROM account_preferences WHERE user_id = u.id AND name = 'email_auth_factor' ORDER BY created_at DESC LIMIT 1), false) as \"email_auth_factor!\"\n FROM users u\n JOIN user_keys k ON u.id = k.user_id\n WHERE u.handle = $1 OR u.email = $1 OR u.did = $1", 4 - "describe": { 5 - "columns": [ 6 - { 7 - "ordinal": 0, 8 - "name": "id", 9 - "type_info": "Uuid" 10 - }, 11 - { 12 - "ordinal": 1, 13 - "name": "did", 14 - "type_info": "Text" 15 - }, 16 - { 17 - "ordinal": 2, 18 - "name": "handle", 19 - "type_info": "Text" 20 - }, 21 - { 22 - "ordinal": 3, 23 - "name": "password_hash", 24 - "type_info": "Text" 25 - }, 26 - { 27 - "ordinal": 4, 28 - "name": "email", 29 - "type_info": "Text" 30 - }, 31 - { 32 - "ordinal": 5, 33 - "name": "deactivated_at", 34 - "type_info": "Timestamptz" 35 - }, 36 - { 37 - "ordinal": 6, 38 - "name": "takedown_ref", 39 - "type_info": "Text" 40 - }, 41 - { 42 - "ordinal": 7, 43 - "name": "email_verified", 44 - "type_info": "Bool" 45 - }, 46 - { 47 - "ordinal": 8, 48 - "name": "discord_verified", 49 - "type_info": "Bool" 50 - }, 51 - { 52 - "ordinal": 9, 53 - "name": "telegram_verified", 54 - "type_info": "Bool" 55 - }, 56 - { 57 - "ordinal": 10, 58 - "name": "signal_verified", 59 - "type_info": "Bool" 60 - }, 61 - { 62 - "ordinal": 11, 63 - "name": "allow_legacy_login", 64 - "type_info": "Bool" 65 - }, 66 - { 67 - "ordinal": 12, 68 - "name": "migrated_to_pds", 69 - "type_info": "Text" 70 - }, 71 - { 72 - "ordinal": 13, 73 - "name": "preferred_comms_channel: CommsChannel", 74 - "type_info": { 75 - "Custom": { 76 - "name": "comms_channel", 77 - "kind": { 78 - "Enum": [ 79 - "email", 80 - "discord", 81 - "telegram", 82 - "signal" 83 - ] 84 - } 85 - } 86 - } 87 - }, 88 - { 89 - "ordinal": 14, 90 - "name": "key_bytes", 91 - "type_info": "Bytea" 92 - }, 93 - { 94 - "ordinal": 15, 95 - "name": "encryption_version", 96 - "type_info": "Int4" 97 - }, 98 - { 99 - "ordinal": 16, 100 - "name": "totp_enabled", 101 - "type_info": "Bool" 102 - }, 103 - { 104 - "ordinal": 17, 105 - "name": "email_auth_factor!", 106 - "type_info": "Bool" 107 - } 108 - ], 109 - "parameters": { 110 - "Left": [ 111 - "Text" 112 - ] 113 - }, 114 - "nullable": [ 115 - false, 116 - false, 117 - false, 118 - true, 119 - true, 120 - true, 121 - true, 122 - false, 123 - false, 124 - false, 125 - false, 126 - false, 127 - true, 128 - false, 129 - false, 130 - true, 131 - null, 132 - null 133 - ] 134 - }, 135 - "hash": "15333a3aa7fff82a603352d5f1bcff7b36510e86145a5e216948641318cc3229" 136 - }
.sqlx/query-297fcbb356d65aae3faae5430000b6c6fbec8566a4adbb595c91606fdfa3bedc.json

This file has not been changed.

.sqlx/query-3b056b9e79847c8bbb8507f283213e7209b417e7933f5b2277a83cae7e1c7888.json

This file has not been changed.

-118
.sqlx/query-3cb8b2be81ead9f3a775c8ad5b7686b040824c20fa69a77f797b0ffbfc6d4f6f.json
··· 1 - { 2 - "db_name": "PostgreSQL", 3 - "query": "\n SELECT u.handle, u.email, u.email_verified, u.is_admin, u.deactivated_at, u.takedown_ref,\n u.preferred_locale,\n u.preferred_comms_channel as \"preferred_comms_channel!: CommsChannel\",\n u.discord_verified, u.telegram_verified, u.signal_verified,\n u.migrated_to_pds, u.migrated_at,\n (SELECT verified FROM user_totp WHERE did = u.did) as totp_enabled,\n COALESCE((SELECT (value_json)::boolean FROM account_preferences WHERE user_id = u.id AND name = 'email_auth_factor' ORDER BY created_at DESC LIMIT 1), false) as \"email_auth_factor!\"\n FROM users u\n WHERE u.did = $1\n ", 4 - "describe": { 5 - "columns": [ 6 - { 7 - "ordinal": 0, 8 - "name": "handle", 9 - "type_info": "Text" 10 - }, 11 - { 12 - "ordinal": 1, 13 - "name": "email", 14 - "type_info": "Text" 15 - }, 16 - { 17 - "ordinal": 2, 18 - "name": "email_verified", 19 - "type_info": "Bool" 20 - }, 21 - { 22 - "ordinal": 3, 23 - "name": "is_admin", 24 - "type_info": "Bool" 25 - }, 26 - { 27 - "ordinal": 4, 28 - "name": "deactivated_at", 29 - "type_info": "Timestamptz" 30 - }, 31 - { 32 - "ordinal": 5, 33 - "name": "takedown_ref", 34 - "type_info": "Text" 35 - }, 36 - { 37 - "ordinal": 6, 38 - "name": "preferred_locale", 39 - "type_info": "Varchar" 40 - }, 41 - { 42 - "ordinal": 7, 43 - "name": "preferred_comms_channel!: CommsChannel", 44 - "type_info": { 45 - "Custom": { 46 - "name": "comms_channel", 47 - "kind": { 48 - "Enum": [ 49 - "email", 50 - "discord", 51 - "telegram", 52 - "signal" 53 - ] 54 - } 55 - } 56 - } 57 - }, 58 - { 59 - "ordinal": 8, 60 - "name": "discord_verified", 61 - "type_info": "Bool" 62 - }, 63 - { 64 - "ordinal": 9, 65 - "name": "telegram_verified", 66 - "type_info": "Bool" 67 - }, 68 - { 69 - "ordinal": 10, 70 - "name": "signal_verified", 71 - "type_info": "Bool" 72 - }, 73 - { 74 - "ordinal": 11, 75 - "name": "migrated_to_pds", 76 - "type_info": "Text" 77 - }, 78 - { 79 - "ordinal": 12, 80 - "name": "migrated_at", 81 - "type_info": "Timestamptz" 82 - }, 83 - { 84 - "ordinal": 13, 85 - "name": "totp_enabled", 86 - "type_info": "Bool" 87 - }, 88 - { 89 - "ordinal": 14, 90 - "name": "email_auth_factor!", 91 - "type_info": "Bool" 92 - } 93 - ], 94 - "parameters": { 95 - "Left": [ 96 - "Text" 97 - ] 98 - }, 99 - "nullable": [ 100 - false, 101 - true, 102 - false, 103 - false, 104 - true, 105 - true, 106 - true, 107 - false, 108 - false, 109 - false, 110 - false, 111 - true, 112 - true, 113 - null, 114 - null 115 - ] 116 - }, 117 - "hash": "3cb8b2be81ead9f3a775c8ad5b7686b040824c20fa69a77f797b0ffbfc6d4f6f" 118 - }
-118
.sqlx/query-44c90cd5796522555f560ecea17297ef0f17c0a127b785e6636e3f40aecf6a99.json
··· 1 - { 2 - "db_name": "PostgreSQL", 3 - "query": "\n SELECT u.handle, u.email, u.email_verified, u.is_admin, u.deactivated_at, u.takedown_ref,\n u.preferred_locale,\n u.preferred_comms_channel as \"preferred_comms_channel!: CommsChannel\",\n u.discord_verified, u.telegram_verified, u.signal_verified,\n u.migrated_to_pds, u.migrated_at,\n (SELECT verified FROM user_totp WHERE did = u.did) as totp_enabled,\n COALESCE((SELECT (value_json)::boolean FROM account_preferences WHERE user_id = u.id AND name = 'email_auth_factor'), false) as \"email_auth_factor!\"\n FROM users u\n WHERE u.did = $1\n ", 4 - "describe": { 5 - "columns": [ 6 - { 7 - "ordinal": 0, 8 - "name": "handle", 9 - "type_info": "Text" 10 - }, 11 - { 12 - "ordinal": 1, 13 - "name": "email", 14 - "type_info": "Text" 15 - }, 16 - { 17 - "ordinal": 2, 18 - "name": "email_verified", 19 - "type_info": "Bool" 20 - }, 21 - { 22 - "ordinal": 3, 23 - "name": "is_admin", 24 - "type_info": "Bool" 25 - }, 26 - { 27 - "ordinal": 4, 28 - "name": "deactivated_at", 29 - "type_info": "Timestamptz" 30 - }, 31 - { 32 - "ordinal": 5, 33 - "name": "takedown_ref", 34 - "type_info": "Text" 35 - }, 36 - { 37 - "ordinal": 6, 38 - "name": "preferred_locale", 39 - "type_info": "Varchar" 40 - }, 41 - { 42 - "ordinal": 7, 43 - "name": "preferred_comms_channel!: CommsChannel", 44 - "type_info": { 45 - "Custom": { 46 - "name": "comms_channel", 47 - "kind": { 48 - "Enum": [ 49 - "email", 50 - "discord", 51 - "telegram", 52 - "signal" 53 - ] 54 - } 55 - } 56 - } 57 - }, 58 - { 59 - "ordinal": 8, 60 - "name": "discord_verified", 61 - "type_info": "Bool" 62 - }, 63 - { 64 - "ordinal": 9, 65 - "name": "telegram_verified", 66 - "type_info": "Bool" 67 - }, 68 - { 69 - "ordinal": 10, 70 - "name": "signal_verified", 71 - "type_info": "Bool" 72 - }, 73 - { 74 - "ordinal": 11, 75 - "name": "migrated_to_pds", 76 - "type_info": "Text" 77 - }, 78 - { 79 - "ordinal": 12, 80 - "name": "migrated_at", 81 - "type_info": "Timestamptz" 82 - }, 83 - { 84 - "ordinal": 13, 85 - "name": "totp_enabled", 86 - "type_info": "Bool" 87 - }, 88 - { 89 - "ordinal": 14, 90 - "name": "email_auth_factor!", 91 - "type_info": "Bool" 92 - } 93 - ], 94 - "parameters": { 95 - "Left": [ 96 - "Text" 97 - ] 98 - }, 99 - "nullable": [ 100 - false, 101 - true, 102 - false, 103 - false, 104 - true, 105 - true, 106 - true, 107 - false, 108 - false, 109 - false, 110 - false, 111 - true, 112 - true, 113 - null, 114 - null 115 - ] 116 - }, 117 - "hash": "44c90cd5796522555f560ecea17297ef0f17c0a127b785e6636e3f40aecf6a99" 118 - }
-136
.sqlx/query-98c5d88ebaf035b3519adaf2c41ba60ba61a110c98d418bed4273f7fa711a916.json
··· 1 - { 2 - "db_name": "PostgreSQL", 3 - "query": "SELECT\n u.id, u.did, u.handle, u.password_hash, u.email, u.deactivated_at, u.takedown_ref,\n u.email_verified, u.discord_verified, u.telegram_verified, u.signal_verified,\n u.allow_legacy_login, u.migrated_to_pds,\n u.preferred_comms_channel as \"preferred_comms_channel: CommsChannel\",\n k.key_bytes, k.encryption_version,\n (SELECT verified FROM user_totp WHERE did = u.did) as totp_enabled,\n COALESCE((SELECT (value_json)::boolean FROM account_preferences WHERE user_id = u.id AND name = 'email_auth_factor'), false) as \"email_auth_factor!\"\n FROM users u\n JOIN user_keys k ON u.id = k.user_id\n WHERE u.handle = $1 OR u.email = $1 OR u.did = $1", 4 - "describe": { 5 - "columns": [ 6 - { 7 - "ordinal": 0, 8 - "name": "id", 9 - "type_info": "Uuid" 10 - }, 11 - { 12 - "ordinal": 1, 13 - "name": "did", 14 - "type_info": "Text" 15 - }, 16 - { 17 - "ordinal": 2, 18 - "name": "handle", 19 - "type_info": "Text" 20 - }, 21 - { 22 - "ordinal": 3, 23 - "name": "password_hash", 24 - "type_info": "Text" 25 - }, 26 - { 27 - "ordinal": 4, 28 - "name": "email", 29 - "type_info": "Text" 30 - }, 31 - { 32 - "ordinal": 5, 33 - "name": "deactivated_at", 34 - "type_info": "Timestamptz" 35 - }, 36 - { 37 - "ordinal": 6, 38 - "name": "takedown_ref", 39 - "type_info": "Text" 40 - }, 41 - { 42 - "ordinal": 7, 43 - "name": "email_verified", 44 - "type_info": "Bool" 45 - }, 46 - { 47 - "ordinal": 8, 48 - "name": "discord_verified", 49 - "type_info": "Bool" 50 - }, 51 - { 52 - "ordinal": 9, 53 - "name": "telegram_verified", 54 - "type_info": "Bool" 55 - }, 56 - { 57 - "ordinal": 10, 58 - "name": "signal_verified", 59 - "type_info": "Bool" 60 - }, 61 - { 62 - "ordinal": 11, 63 - "name": "allow_legacy_login", 64 - "type_info": "Bool" 65 - }, 66 - { 67 - "ordinal": 12, 68 - "name": "migrated_to_pds", 69 - "type_info": "Text" 70 - }, 71 - { 72 - "ordinal": 13, 73 - "name": "preferred_comms_channel: CommsChannel", 74 - "type_info": { 75 - "Custom": { 76 - "name": "comms_channel", 77 - "kind": { 78 - "Enum": [ 79 - "email", 80 - "discord", 81 - "telegram", 82 - "signal" 83 - ] 84 - } 85 - } 86 - } 87 - }, 88 - { 89 - "ordinal": 14, 90 - "name": "key_bytes", 91 - "type_info": "Bytea" 92 - }, 93 - { 94 - "ordinal": 15, 95 - "name": "encryption_version", 96 - "type_info": "Int4" 97 - }, 98 - { 99 - "ordinal": 16, 100 - "name": "totp_enabled", 101 - "type_info": "Bool" 102 - }, 103 - { 104 - "ordinal": 17, 105 - "name": "email_auth_factor!", 106 - "type_info": "Bool" 107 - } 108 - ], 109 - "parameters": { 110 - "Left": [ 111 - "Text" 112 - ] 113 - }, 114 - "nullable": [ 115 - false, 116 - false, 117 - false, 118 - true, 119 - true, 120 - true, 121 - true, 122 - false, 123 - false, 124 - false, 125 - false, 126 - false, 127 - true, 128 - false, 129 - false, 130 - true, 131 - null, 132 - null 133 - ] 134 - }, 135 - "hash": "98c5d88ebaf035b3519adaf2c41ba60ba61a110c98d418bed4273f7fa711a916" 136 - }
crates/tranquil-cache/src/lib.rs

This file has not been changed.

crates/tranquil-comms/src/locale.rs

This file has not been changed.

+2 -2
crates/tranquil-db-traits/src/user.rs
··· 769 769 pub migrated_to_pds: Option<String>, 770 770 pub migrated_at: Option<DateTime<Utc>>, 771 771 pub totp_enabled: bool, 772 - pub email_auth_factor: bool, 772 + pub email_2fa_enabled: bool, 773 773 } 774 774 775 775 #[derive(Debug, Clone)] ··· 794 794 pub key_bytes: Vec<u8>, 795 795 pub encryption_version: Option<i32>, 796 796 pub totp_enabled: bool, 797 - pub email_auth_factor: bool, 797 + pub email_2fa_enabled: bool, 798 798 } 799 799 800 800 #[derive(Debug, Clone)]
crates/tranquil-db/src/postgres/infra.rs

This file has not been changed.

+4 -4
crates/tranquil-db/src/postgres/user.rs
··· 1380 1380 u.discord_verified, u.telegram_verified, u.signal_verified, 1381 1381 u.migrated_to_pds, u.migrated_at, 1382 1382 (SELECT verified FROM user_totp WHERE did = u.did) as totp_enabled, 1383 - COALESCE((SELECT (value_json)::boolean FROM account_preferences WHERE user_id = u.id AND name = 'email_auth_factor' ORDER BY created_at DESC LIMIT 1), false) as "email_auth_factor!" 1383 + COALESCE((SELECT (value_json)::boolean FROM account_preferences WHERE user_id = u.id AND name = 'email_auth_factor' ORDER BY created_at DESC LIMIT 1), false) as "email_2fa_enabled!" 1384 1384 FROM users u 1385 1385 WHERE u.did = $1 1386 1386 "#, ··· 1407 1407 migrated_to_pds: row.migrated_to_pds, 1408 1408 migrated_at: row.migrated_at, 1409 1409 totp_enabled: row.totp_enabled.unwrap_or(false), 1410 - email_auth_factor: row.email_auth_factor, 1410 + email_2fa_enabled: row.email_2fa_enabled, 1411 1411 }) 1412 1412 }) 1413 1413 } ··· 1473 1473 u.preferred_comms_channel as "preferred_comms_channel: CommsChannel", 1474 1474 k.key_bytes, k.encryption_version, 1475 1475 (SELECT verified FROM user_totp WHERE did = u.did) as totp_enabled, 1476 - COALESCE((SELECT (value_json)::boolean FROM account_preferences WHERE user_id = u.id AND name = 'email_auth_factor' ORDER BY created_at DESC LIMIT 1), false) as "email_auth_factor!" 1476 + COALESCE((SELECT (value_json)::boolean FROM account_preferences WHERE user_id = u.id AND name = 'email_auth_factor' ORDER BY created_at DESC LIMIT 1), false) as "email_2fa_enabled!" 1477 1477 FROM users u 1478 1478 JOIN user_keys k ON u.id = k.user_id 1479 1479 WHERE u.handle = $1 OR u.email = $1 OR u.did = $1"#, ··· 1503 1503 key_bytes: row.key_bytes, 1504 1504 encryption_version: row.encryption_version, 1505 1505 totp_enabled: row.totp_enabled.unwrap_or(false), 1506 - email_auth_factor: row.email_auth_factor, 1506 + email_2fa_enabled: row.email_2fa_enabled, 1507 1507 }) 1508 1508 }) 1509 1509 }
crates/tranquil-infra/src/lib.rs

This file has not been changed.

crates/tranquil-pds/src/api/error.rs

This file has not been changed.

crates/tranquil-pds/src/api/server/email.rs

This file has not been changed.

+5 -5
crates/tranquil-pds/src/api/server/session.rs
··· 161 161 .into_response(); 162 162 } 163 163 let has_totp = row.totp_enabled; 164 - let email_auth_factor = row.email_auth_factor; 165 - let is_legacy_login = has_totp || email_auth_factor; 164 + let email_2fa_enabled = row.email_2fa_enabled; 165 + let is_legacy_login = has_totp || email_2fa_enabled; 166 166 let twofa_ctx = crate::auth::legacy_2fa::Legacy2faContext { 167 - email_auth_factor, 167 + email_2fa_enabled, 168 168 has_totp, 169 169 allow_legacy_login: row.allow_legacy_login, 170 170 }; ··· 303 303 let handle = full_handle(&row.handle, pds_host); 304 304 let is_active = account_state.is_active(); 305 305 let status = account_state.status_for_session().map(String::from); 306 - let email_auth_factor_out = if email_auth_factor || has_totp { 306 + let email_auth_factor_out = if email_2fa_enabled || has_totp { 307 307 Some(true) 308 308 } else { 309 309 None ··· 374 374 response["email"] = json!(email_value); 375 375 response["emailConfirmed"] = json!(email_confirmed_value); 376 376 } 377 - if row.email_auth_factor || row.totp_enabled { 377 + if row.email_2fa_enabled || row.totp_enabled { 378 378 response["emailAuthFactor"] = json!(true); 379 379 } 380 380 if let Some(status) = account_state.status_for_session() {
crates/tranquil-pds/src/api/server/totp.rs

This file has not been changed.

crates/tranquil-pds/src/auth/email_token.rs

This file has not been changed.

+9 -9
crates/tranquil-pds/src/auth/legacy_2fa.rs
··· 156 156 } 157 157 158 158 pub struct Legacy2faContext { 159 - pub email_auth_factor: bool, 159 + pub email_2fa_enabled: bool, 160 160 pub has_totp: bool, 161 161 pub allow_legacy_login: bool, 162 162 } 163 163 164 164 impl Legacy2faContext { 165 165 pub fn requires_2fa(&self) -> bool { 166 - self.email_auth_factor || self.has_totp 166 + self.email_2fa_enabled || self.has_totp 167 167 } 168 168 169 169 pub fn is_blocked(&self) -> bool { 170 - self.has_totp && !self.allow_legacy_login && !self.email_auth_factor 170 + self.has_totp && !self.allow_legacy_login && !self.email_2fa_enabled 171 171 } 172 172 } 173 173 ··· 418 418 let cache = MockCache::new(); 419 419 let did = Did::new("did:plc:test".to_string()).unwrap(); 420 420 let ctx = Legacy2faContext { 421 - email_auth_factor: false, 421 + email_2fa_enabled: false, 422 422 has_totp: false, 423 423 allow_legacy_login: true, 424 424 }; ··· 432 432 let cache = MockCache::new(); 433 433 let did = Did::new("did:plc:test".to_string()).unwrap(); 434 434 let ctx = Legacy2faContext { 435 - email_auth_factor: false, 435 + email_2fa_enabled: false, 436 436 has_totp: true, 437 437 allow_legacy_login: false, 438 438 }; ··· 446 446 let cache = MockCache::new(); 447 447 let did = Did::new("did:plc:test".to_string()).unwrap(); 448 448 let ctx = Legacy2faContext { 449 - email_auth_factor: false, 449 + email_2fa_enabled: false, 450 450 has_totp: true, 451 451 allow_legacy_login: true, 452 452 }; ··· 456 456 } 457 457 458 458 #[tokio::test] 459 - async fn test_process_flow_challenge_sent_email_auth_factor() { 459 + async fn test_process_flow_challenge_sent_email_2fa_enabled() { 460 460 let cache = MockCache::new(); 461 461 let did = Did::new("did:plc:test2".to_string()).unwrap(); 462 462 let ctx = Legacy2faContext { 463 - email_auth_factor: true, 463 + email_2fa_enabled: true, 464 464 has_totp: false, 465 465 allow_legacy_login: false, 466 466 }; ··· 474 474 let cache = MockCache::new(); 475 475 let did = Did::new("did:plc:test".to_string()).unwrap(); 476 476 let ctx = Legacy2faContext { 477 - email_auth_factor: true, 477 + email_2fa_enabled: true, 478 478 has_totp: false, 479 479 allow_legacy_login: false, 480 480 };
crates/tranquil-pds/src/auth/mod.rs

This file has not been changed.

crates/tranquil-pds/src/comms/service.rs

This file has not been changed.

crates/tranquil-pds/tests/actor.rs

This file has not been changed.

crates/tranquil-pds/tests/legacy_2fa.rs

This file has not been changed.

crates/tranquil-pds/tests/shutdown_unit.rs

This file has not been changed.

+136
.sqlx/query-a960b981a146a0e422ef53601dfc31e29cf777aa194227c48c6ebc6905ea3249.json
··· 1 + { 2 + "db_name": "PostgreSQL", 3 + "query": "SELECT\n u.id, u.did, u.handle, u.password_hash, u.email, u.deactivated_at, u.takedown_ref,\n u.email_verified, u.discord_verified, u.telegram_verified, u.signal_verified,\n u.allow_legacy_login, u.migrated_to_pds,\n u.preferred_comms_channel as \"preferred_comms_channel: CommsChannel\",\n k.key_bytes, k.encryption_version,\n (SELECT verified FROM user_totp WHERE did = u.did) as totp_enabled,\n COALESCE((SELECT (value_json)::boolean FROM account_preferences WHERE user_id = u.id AND name = 'email_auth_factor' ORDER BY created_at DESC LIMIT 1), false) as \"email_2fa_enabled!\"\n FROM users u\n JOIN user_keys k ON u.id = k.user_id\n WHERE u.handle = $1 OR u.email = $1 OR u.did = $1", 4 + "describe": { 5 + "columns": [ 6 + { 7 + "ordinal": 0, 8 + "name": "id", 9 + "type_info": "Uuid" 10 + }, 11 + { 12 + "ordinal": 1, 13 + "name": "did", 14 + "type_info": "Text" 15 + }, 16 + { 17 + "ordinal": 2, 18 + "name": "handle", 19 + "type_info": "Text" 20 + }, 21 + { 22 + "ordinal": 3, 23 + "name": "password_hash", 24 + "type_info": "Text" 25 + }, 26 + { 27 + "ordinal": 4, 28 + "name": "email", 29 + "type_info": "Text" 30 + }, 31 + { 32 + "ordinal": 5, 33 + "name": "deactivated_at", 34 + "type_info": "Timestamptz" 35 + }, 36 + { 37 + "ordinal": 6, 38 + "name": "takedown_ref", 39 + "type_info": "Text" 40 + }, 41 + { 42 + "ordinal": 7, 43 + "name": "email_verified", 44 + "type_info": "Bool" 45 + }, 46 + { 47 + "ordinal": 8, 48 + "name": "discord_verified", 49 + "type_info": "Bool" 50 + }, 51 + { 52 + "ordinal": 9, 53 + "name": "telegram_verified", 54 + "type_info": "Bool" 55 + }, 56 + { 57 + "ordinal": 10, 58 + "name": "signal_verified", 59 + "type_info": "Bool" 60 + }, 61 + { 62 + "ordinal": 11, 63 + "name": "allow_legacy_login", 64 + "type_info": "Bool" 65 + }, 66 + { 67 + "ordinal": 12, 68 + "name": "migrated_to_pds", 69 + "type_info": "Text" 70 + }, 71 + { 72 + "ordinal": 13, 73 + "name": "preferred_comms_channel: CommsChannel", 74 + "type_info": { 75 + "Custom": { 76 + "name": "comms_channel", 77 + "kind": { 78 + "Enum": [ 79 + "email", 80 + "discord", 81 + "telegram", 82 + "signal" 83 + ] 84 + } 85 + } 86 + } 87 + }, 88 + { 89 + "ordinal": 14, 90 + "name": "key_bytes", 91 + "type_info": "Bytea" 92 + }, 93 + { 94 + "ordinal": 15, 95 + "name": "encryption_version", 96 + "type_info": "Int4" 97 + }, 98 + { 99 + "ordinal": 16, 100 + "name": "totp_enabled", 101 + "type_info": "Bool" 102 + }, 103 + { 104 + "ordinal": 17, 105 + "name": "email_2fa_enabled!", 106 + "type_info": "Bool" 107 + } 108 + ], 109 + "parameters": { 110 + "Left": [ 111 + "Text" 112 + ] 113 + }, 114 + "nullable": [ 115 + false, 116 + false, 117 + false, 118 + true, 119 + true, 120 + true, 121 + true, 122 + false, 123 + false, 124 + false, 125 + false, 126 + false, 127 + true, 128 + false, 129 + false, 130 + true, 131 + null, 132 + null 133 + ] 134 + }, 135 + "hash": "a960b981a146a0e422ef53601dfc31e29cf777aa194227c48c6ebc6905ea3249" 136 + }
+118
.sqlx/query-c8728a1247c535e941e2b3bcb4100d7b3610f31c7acfdc1f8c072e1c5ca0ea18.json
··· 1 + { 2 + "db_name": "PostgreSQL", 3 + "query": "\n SELECT u.handle, u.email, u.email_verified, u.is_admin, u.deactivated_at, u.takedown_ref,\n u.preferred_locale,\n u.preferred_comms_channel as \"preferred_comms_channel!: CommsChannel\",\n u.discord_verified, u.telegram_verified, u.signal_verified,\n u.migrated_to_pds, u.migrated_at,\n (SELECT verified FROM user_totp WHERE did = u.did) as totp_enabled,\n COALESCE((SELECT (value_json)::boolean FROM account_preferences WHERE user_id = u.id AND name = 'email_auth_factor' ORDER BY created_at DESC LIMIT 1), false) as \"email_2fa_enabled!\"\n FROM users u\n WHERE u.did = $1\n ", 4 + "describe": { 5 + "columns": [ 6 + { 7 + "ordinal": 0, 8 + "name": "handle", 9 + "type_info": "Text" 10 + }, 11 + { 12 + "ordinal": 1, 13 + "name": "email", 14 + "type_info": "Text" 15 + }, 16 + { 17 + "ordinal": 2, 18 + "name": "email_verified", 19 + "type_info": "Bool" 20 + }, 21 + { 22 + "ordinal": 3, 23 + "name": "is_admin", 24 + "type_info": "Bool" 25 + }, 26 + { 27 + "ordinal": 4, 28 + "name": "deactivated_at", 29 + "type_info": "Timestamptz" 30 + }, 31 + { 32 + "ordinal": 5, 33 + "name": "takedown_ref", 34 + "type_info": "Text" 35 + }, 36 + { 37 + "ordinal": 6, 38 + "name": "preferred_locale", 39 + "type_info": "Varchar" 40 + }, 41 + { 42 + "ordinal": 7, 43 + "name": "preferred_comms_channel!: CommsChannel", 44 + "type_info": { 45 + "Custom": { 46 + "name": "comms_channel", 47 + "kind": { 48 + "Enum": [ 49 + "email", 50 + "discord", 51 + "telegram", 52 + "signal" 53 + ] 54 + } 55 + } 56 + } 57 + }, 58 + { 59 + "ordinal": 8, 60 + "name": "discord_verified", 61 + "type_info": "Bool" 62 + }, 63 + { 64 + "ordinal": 9, 65 + "name": "telegram_verified", 66 + "type_info": "Bool" 67 + }, 68 + { 69 + "ordinal": 10, 70 + "name": "signal_verified", 71 + "type_info": "Bool" 72 + }, 73 + { 74 + "ordinal": 11, 75 + "name": "migrated_to_pds", 76 + "type_info": "Text" 77 + }, 78 + { 79 + "ordinal": 12, 80 + "name": "migrated_at", 81 + "type_info": "Timestamptz" 82 + }, 83 + { 84 + "ordinal": 13, 85 + "name": "totp_enabled", 86 + "type_info": "Bool" 87 + }, 88 + { 89 + "ordinal": 14, 90 + "name": "email_2fa_enabled!", 91 + "type_info": "Bool" 92 + } 93 + ], 94 + "parameters": { 95 + "Left": [ 96 + "Text" 97 + ] 98 + }, 99 + "nullable": [ 100 + false, 101 + true, 102 + false, 103 + false, 104 + true, 105 + true, 106 + true, 107 + false, 108 + false, 109 + false, 110 + false, 111 + true, 112 + true, 113 + null, 114 + null 115 + ] 116 + }, 117 + "hash": "c8728a1247c535e941e2b3bcb4100d7b3610f31c7acfdc1f8c072e1c5ca0ea18" 118 + }

History

2 rounds 2 comments
sign up or login to add to the discussion
lewis.moe submitted #1
1 commit
expand
feat: legacy 2fa impl
expand 0 comments
pull request successfully merged
lewis.moe submitted #0
1 commit
expand
feat: legacy 2fa impl
expand 2 comments

nitpicky but id prefer email_auth_factor in crates/tranquil-db-traits/src/user.rs be called email_2fa_enabled instead. lines up with totp_enabled and is more descriptive

might wanna double check that youve run cargo fmt cause my gut tells me rustfmt wouldnt allow ) .await { and would instead do ).await { but if it does the former it does that ig ...

ok fixed!