forked from
tranquil.farm/tranquil-pds
Our Personal Data Server from scratch!
1use async_trait::async_trait;
2use chrono::{DateTime, Utc};
3use serde::{Deserialize, Serialize};
4use tranquil_types::{Did, Handle};
5use uuid::Uuid;
6
7use crate::{ChannelVerificationStatus, CommsChannel, DbError, SsoProviderType};
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10pub enum WebauthnChallengeType {
11 Registration,
12 Authentication,
13}
14
15impl WebauthnChallengeType {
16 pub fn as_str(self) -> &'static str {
17 match self {
18 Self::Registration => "registration",
19 Self::Authentication => "authentication",
20 }
21 }
22}
23
24#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, sqlx::Type)]
25#[sqlx(type_name = "account_type", rename_all = "snake_case")]
26pub enum AccountType {
27 Personal,
28 Delegated,
29}
30
31impl AccountType {
32 pub fn is_delegated(&self) -> bool {
33 matches!(self, Self::Delegated)
34 }
35}
36
37#[derive(Debug, Clone)]
38pub struct UserRow {
39 pub id: Uuid,
40 pub did: Did,
41 pub handle: Handle,
42 pub email: Option<String>,
43 pub created_at: DateTime<Utc>,
44 pub deactivated_at: Option<DateTime<Utc>>,
45 pub takedown_ref: Option<String>,
46 pub is_admin: bool,
47}
48
49#[derive(Debug, Clone)]
50pub struct UserWithKey {
51 pub id: Uuid,
52 pub did: Did,
53 pub handle: Handle,
54 pub email: Option<String>,
55 pub deactivated_at: Option<DateTime<Utc>>,
56 pub takedown_ref: Option<String>,
57 pub is_admin: bool,
58 pub key_bytes: Vec<u8>,
59 pub encryption_version: Option<i32>,
60}
61
62#[derive(Debug, Clone)]
63pub struct UserStatus {
64 pub deactivated_at: Option<DateTime<Utc>>,
65 pub takedown_ref: Option<String>,
66 pub is_admin: bool,
67}
68
69#[derive(Debug, Clone)]
70pub struct UserEmailInfo {
71 pub id: Uuid,
72 pub handle: Handle,
73 pub email: Option<String>,
74 pub email_verified: bool,
75}
76
77#[derive(Debug, Clone)]
78pub struct UserLoginCheck {
79 pub did: Did,
80 pub password_hash: Option<String>,
81}
82
83#[derive(Debug, Clone)]
84pub struct UserLoginInfo {
85 pub id: Uuid,
86 pub did: Did,
87 pub email: Option<String>,
88 pub password_hash: Option<String>,
89 pub password_required: bool,
90 pub two_factor_enabled: bool,
91 pub preferred_comms_channel: CommsChannel,
92 pub deactivated_at: Option<DateTime<Utc>>,
93 pub takedown_ref: Option<String>,
94 pub channel_verification: ChannelVerificationStatus,
95 pub account_type: AccountType,
96}
97
98#[derive(Debug, Clone)]
99pub struct User2faStatus {
100 pub id: Uuid,
101 pub two_factor_enabled: bool,
102 pub preferred_comms_channel: CommsChannel,
103 pub channel_verification: ChannelVerificationStatus,
104}
105
106#[async_trait]
107pub trait UserRepository: Send + Sync {
108 async fn get_by_did(&self, did: &Did) -> Result<Option<UserRow>, DbError>;
109
110 async fn get_by_handle(&self, handle: &Handle) -> Result<Option<UserRow>, DbError>;
111
112 async fn get_with_key_by_did(&self, did: &Did) -> Result<Option<UserWithKey>, DbError>;
113
114 async fn get_status_by_did(&self, did: &Did) -> Result<Option<UserStatus>, DbError>;
115
116 async fn count_users(&self) -> Result<i64, DbError>;
117
118 async fn get_session_access_expiry(
119 &self,
120 did: &Did,
121 access_jti: &str,
122 ) -> Result<Option<DateTime<Utc>>, DbError>;
123
124 async fn get_oauth_token_with_user(
125 &self,
126 token_id: &str,
127 ) -> Result<Option<OAuthTokenWithUser>, DbError>;
128
129 async fn get_user_info_by_did(&self, did: &Did) -> Result<Option<UserInfoForAuth>, DbError>;
130
131 async fn get_any_admin_user_id(&self) -> Result<Option<Uuid>, DbError>;
132
133 async fn set_invites_disabled(&self, did: &Did, disabled: bool) -> Result<bool, DbError>;
134
135 async fn search_accounts(
136 &self,
137 cursor_did: Option<&Did>,
138 email_filter: Option<&str>,
139 handle_filter: Option<&str>,
140 limit: i64,
141 ) -> Result<Vec<AccountSearchResult>, DbError>;
142
143 async fn get_auth_info_by_did(&self, did: &Did) -> Result<Option<UserAuthInfo>, DbError>;
144
145 async fn get_by_email(&self, email: &str) -> Result<Option<UserForVerification>, DbError>;
146
147 async fn get_login_check_by_handle_or_email(
148 &self,
149 identifier: &str,
150 ) -> Result<Option<UserLoginCheck>, DbError>;
151
152 async fn get_login_info_by_handle_or_email(
153 &self,
154 identifier: &str,
155 ) -> Result<Option<UserLoginInfo>, DbError>;
156
157 async fn get_2fa_status_by_did(&self, did: &Did) -> Result<Option<User2faStatus>, DbError>;
158
159 async fn get_comms_prefs(&self, user_id: Uuid) -> Result<Option<UserCommsPrefs>, DbError>;
160
161 async fn get_id_by_did(&self, did: &Did) -> Result<Option<Uuid>, DbError>;
162
163 async fn get_user_key_by_id(&self, user_id: Uuid) -> Result<Option<UserKeyInfo>, DbError>;
164
165 async fn get_id_and_handle_by_did(&self, did: &Did)
166 -> Result<Option<UserIdAndHandle>, DbError>;
167
168 async fn get_did_web_info_by_handle(
169 &self,
170 handle: &Handle,
171 ) -> Result<Option<UserDidWebInfo>, DbError>;
172
173 async fn get_did_web_overrides(
174 &self,
175 user_id: Uuid,
176 ) -> Result<Option<DidWebOverrides>, DbError>;
177
178 async fn get_handle_by_did(&self, did: &Did) -> Result<Option<Handle>, DbError>;
179
180 async fn is_account_active_by_did(&self, did: &Did) -> Result<Option<bool>, DbError>;
181
182 async fn get_user_for_deletion(&self, did: &Did) -> Result<Option<UserForDeletion>, DbError>;
183
184 async fn check_handle_exists(
185 &self,
186 handle: &Handle,
187 exclude_user_id: Uuid,
188 ) -> Result<bool, DbError>;
189
190 async fn update_handle(&self, user_id: Uuid, handle: &Handle) -> Result<(), DbError>;
191
192 async fn get_user_with_key_by_did(&self, did: &Did) -> Result<Option<UserKeyWithId>, DbError>;
193
194 async fn is_account_migrated(&self, did: &Did) -> Result<bool, DbError>;
195
196 async fn has_verified_comms_channel(&self, did: &Did) -> Result<bool, DbError>;
197
198 async fn get_id_by_handle(&self, handle: &Handle) -> Result<Option<Uuid>, DbError>;
199
200 async fn get_email_info_by_did(&self, did: &Did) -> Result<Option<UserEmailInfo>, DbError>;
201
202 async fn check_email_exists(&self, email: &str, exclude_user_id: Uuid)
203 -> Result<bool, DbError>;
204
205 async fn update_email(&self, user_id: Uuid, email: &str) -> Result<(), DbError>;
206
207 async fn set_email_verified(&self, user_id: Uuid, verified: bool) -> Result<(), DbError>;
208
209 async fn check_email_verified_by_identifier(
210 &self,
211 identifier: &str,
212 ) -> Result<Option<bool>, DbError>;
213
214 async fn check_channel_verified_by_did(
215 &self,
216 did: &Did,
217 channel: CommsChannel,
218 ) -> Result<Option<bool>, DbError>;
219
220 async fn admin_update_email(&self, did: &Did, email: &str) -> Result<u64, DbError>;
221
222 async fn admin_update_handle(&self, did: &Did, handle: &Handle) -> Result<u64, DbError>;
223
224 async fn admin_update_password(&self, did: &Did, password_hash: &str) -> Result<u64, DbError>;
225
226 async fn set_admin_status(&self, did: &Did, is_admin: bool) -> Result<(), DbError>;
227
228 async fn get_notification_prefs(&self, did: &Did)
229 -> Result<Option<NotificationPrefs>, DbError>;
230
231 async fn get_id_handle_email_by_did(
232 &self,
233 did: &Did,
234 ) -> Result<Option<UserIdHandleEmail>, DbError>;
235
236 async fn update_preferred_comms_channel(
237 &self,
238 did: &Did,
239 channel: CommsChannel,
240 ) -> Result<(), DbError>;
241
242 async fn clear_discord(&self, user_id: Uuid) -> Result<(), DbError>;
243
244 async fn clear_telegram(&self, user_id: Uuid) -> Result<(), DbError>;
245
246 async fn clear_signal(&self, user_id: Uuid) -> Result<(), DbError>;
247
248 async fn set_unverified_signal(
249 &self,
250 user_id: Uuid,
251 signal_username: &str,
252 ) -> Result<(), DbError>;
253
254 async fn set_unverified_telegram(
255 &self,
256 user_id: Uuid,
257 telegram_username: &str,
258 ) -> Result<(), DbError>;
259
260 async fn store_telegram_chat_id(
261 &self,
262 telegram_username: &str,
263 chat_id: i64,
264 handle: Option<&str>,
265 ) -> Result<Option<Uuid>, DbError>;
266
267 async fn get_telegram_chat_id(&self, user_id: Uuid) -> Result<Option<i64>, DbError>;
268
269 async fn set_unverified_discord(
270 &self,
271 user_id: Uuid,
272 discord_username: &str,
273 ) -> Result<(), DbError>;
274
275 async fn store_discord_user_id(
276 &self,
277 discord_username: &str,
278 discord_id: &str,
279 handle: Option<&str>,
280 ) -> Result<Option<Uuid>, DbError>;
281
282 async fn get_verification_info(
283 &self,
284 did: &Did,
285 ) -> Result<Option<UserVerificationInfo>, DbError>;
286
287 async fn verify_email_channel(&self, user_id: Uuid, email: &str) -> Result<bool, DbError>;
288
289 async fn verify_discord_channel(&self, user_id: Uuid, discord_id: &str) -> Result<(), DbError>;
290
291 async fn verify_telegram_channel(
292 &self,
293 user_id: Uuid,
294 telegram_username: &str,
295 ) -> Result<(), DbError>;
296
297 async fn verify_signal_channel(
298 &self,
299 user_id: Uuid,
300 signal_username: &str,
301 ) -> Result<(), DbError>;
302
303 async fn set_email_verified_flag(&self, user_id: Uuid) -> Result<(), DbError>;
304
305 async fn set_discord_verified_flag(&self, user_id: Uuid) -> Result<(), DbError>;
306
307 async fn set_telegram_verified_flag(&self, user_id: Uuid) -> Result<(), DbError>;
308
309 async fn set_signal_verified_flag(&self, user_id: Uuid) -> Result<(), DbError>;
310
311 async fn has_totp_enabled(&self, did: &Did) -> Result<bool, DbError>;
312
313 async fn has_passkeys(&self, did: &Did) -> Result<bool, DbError>;
314
315 async fn get_password_hash_by_did(&self, did: &Did) -> Result<Option<String>, DbError>;
316
317 async fn get_passkeys_for_user(&self, did: &Did) -> Result<Vec<StoredPasskey>, DbError>;
318
319 async fn get_passkey_by_credential_id(
320 &self,
321 credential_id: &[u8],
322 ) -> Result<Option<StoredPasskey>, DbError>;
323
324 async fn save_passkey(
325 &self,
326 did: &Did,
327 credential_id: &[u8],
328 public_key: &[u8],
329 friendly_name: Option<&str>,
330 ) -> Result<Uuid, DbError>;
331
332 async fn update_passkey_counter(
333 &self,
334 credential_id: &[u8],
335 new_counter: i32,
336 ) -> Result<bool, DbError>;
337
338 async fn delete_passkey(&self, id: Uuid, did: &Did) -> Result<bool, DbError>;
339
340 async fn update_passkey_name(&self, id: Uuid, did: &Did, name: &str) -> Result<bool, DbError>;
341
342 async fn save_webauthn_challenge(
343 &self,
344 did: &Did,
345 challenge_type: WebauthnChallengeType,
346 state_json: &str,
347 ) -> Result<Uuid, DbError>;
348
349 async fn load_webauthn_challenge(
350 &self,
351 did: &Did,
352 challenge_type: WebauthnChallengeType,
353 ) -> Result<Option<String>, DbError>;
354
355 async fn delete_webauthn_challenge(
356 &self,
357 did: &Did,
358 challenge_type: WebauthnChallengeType,
359 ) -> Result<(), DbError>;
360
361 async fn get_totp_record(&self, did: &Did) -> Result<Option<TotpRecord>, DbError>;
362
363 async fn get_totp_record_state(&self, did: &Did) -> Result<Option<TotpRecordState>, DbError>;
364
365 async fn upsert_totp_secret(
366 &self,
367 did: &Did,
368 secret_encrypted: &[u8],
369 encryption_version: i32,
370 ) -> Result<(), DbError>;
371
372 async fn set_totp_verified(&self, did: &Did) -> Result<(), DbError>;
373
374 async fn update_totp_last_used(&self, did: &Did) -> Result<(), DbError>;
375
376 async fn delete_totp(&self, did: &Did) -> Result<(), DbError>;
377
378 async fn get_unused_backup_codes(&self, did: &Did) -> Result<Vec<StoredBackupCode>, DbError>;
379
380 async fn mark_backup_code_used(&self, code_id: Uuid) -> Result<bool, DbError>;
381
382 async fn count_unused_backup_codes(&self, did: &Did) -> Result<i64, DbError>;
383
384 async fn delete_backup_codes(&self, did: &Did) -> Result<u64, DbError>;
385
386 async fn insert_backup_codes(&self, did: &Did, code_hashes: &[String]) -> Result<(), DbError>;
387
388 async fn enable_totp_with_backup_codes(
389 &self,
390 did: &Did,
391 code_hashes: &[String],
392 ) -> Result<(), DbError>;
393
394 async fn delete_totp_and_backup_codes(&self, did: &Did) -> Result<(), DbError>;
395
396 async fn replace_backup_codes(&self, did: &Did, code_hashes: &[String]) -> Result<(), DbError>;
397
398 async fn get_session_info_by_did(&self, did: &Did) -> Result<Option<UserSessionInfo>, DbError>;
399
400 async fn get_legacy_login_pref(
401 &self,
402 did: &Did,
403 ) -> Result<Option<UserLegacyLoginPref>, DbError>;
404
405 async fn update_legacy_login(&self, did: &Did, allow: bool) -> Result<bool, DbError>;
406
407 async fn update_locale(&self, did: &Did, locale: &str) -> Result<bool, DbError>;
408
409 async fn get_login_full_by_identifier(
410 &self,
411 identifier: &str,
412 ) -> Result<Option<UserLoginFull>, DbError>;
413
414 async fn get_confirm_signup_by_did(
415 &self,
416 did: &Did,
417 ) -> Result<Option<UserConfirmSignup>, DbError>;
418
419 async fn get_resend_verification_by_did(
420 &self,
421 did: &Did,
422 ) -> Result<Option<UserResendVerification>, DbError>;
423
424 async fn set_channel_verified(&self, did: &Did, channel: CommsChannel) -> Result<(), DbError>;
425
426 async fn get_id_by_email_or_handle(
427 &self,
428 email: &str,
429 handle: &str,
430 ) -> Result<Option<Uuid>, DbError>;
431
432 async fn count_accounts_by_email(&self, email: &str) -> Result<i64, DbError>;
433
434 async fn get_handles_by_email(&self, email: &str) -> Result<Vec<Handle>, DbError>;
435
436 async fn set_password_reset_code(
437 &self,
438 user_id: Uuid,
439 code: &str,
440 expires_at: DateTime<Utc>,
441 ) -> Result<(), DbError>;
442
443 async fn get_user_by_reset_code(
444 &self,
445 code: &str,
446 ) -> Result<Option<UserResetCodeInfo>, DbError>;
447
448 async fn clear_password_reset_code(&self, user_id: Uuid) -> Result<(), DbError>;
449
450 async fn get_id_and_password_hash_by_did(
451 &self,
452 did: &Did,
453 ) -> Result<Option<UserIdAndPasswordHash>, DbError>;
454
455 async fn update_password_hash(&self, user_id: Uuid, password_hash: &str)
456 -> Result<(), DbError>;
457
458 async fn reset_password_with_sessions(
459 &self,
460 user_id: Uuid,
461 password_hash: &str,
462 ) -> Result<PasswordResetResult, DbError>;
463
464 async fn activate_account(&self, did: &Did) -> Result<bool, DbError>;
465
466 async fn deactivate_account(
467 &self,
468 did: &Did,
469 delete_after: Option<DateTime<Utc>>,
470 ) -> Result<bool, DbError>;
471
472 async fn has_password_by_did(&self, did: &Did) -> Result<Option<bool>, DbError>;
473
474 async fn get_password_info_by_did(
475 &self,
476 did: &Did,
477 ) -> Result<Option<UserPasswordInfo>, DbError>;
478
479 async fn remove_user_password(&self, user_id: Uuid) -> Result<(), DbError>;
480
481 async fn set_new_user_password(
482 &self,
483 user_id: Uuid,
484 password_hash: &str,
485 ) -> Result<(), DbError>;
486
487 async fn get_user_key_by_did(&self, did: &Did) -> Result<Option<UserKeyInfo>, DbError>;
488
489 async fn delete_account_complete(&self, user_id: Uuid, did: &Did) -> Result<(), DbError>;
490
491 async fn set_user_takedown(
492 &self,
493 did: &Did,
494 takedown_ref: Option<&str>,
495 ) -> Result<bool, DbError>;
496
497 async fn admin_delete_account_complete(&self, user_id: Uuid, did: &Did) -> Result<(), DbError>;
498
499 async fn get_user_for_did_doc(&self, did: &Did) -> Result<Option<UserForDidDoc>, DbError>;
500
501 async fn get_user_for_did_doc_build(
502 &self,
503 did: &Did,
504 ) -> Result<Option<UserForDidDocBuild>, DbError>;
505
506 async fn upsert_did_web_overrides(
507 &self,
508 user_id: Uuid,
509 verification_methods: Option<serde_json::Value>,
510 also_known_as: Option<Vec<String>>,
511 ) -> Result<(), DbError>;
512
513 async fn update_migrated_to_pds(&self, did: &Did, endpoint: &str) -> Result<(), DbError>;
514
515 async fn get_user_for_passkey_setup(
516 &self,
517 did: &Did,
518 ) -> Result<Option<UserForPasskeySetup>, DbError>;
519
520 async fn get_user_for_passkey_recovery(
521 &self,
522 identifier: &str,
523 normalized_handle: &str,
524 ) -> Result<Option<UserForPasskeyRecovery>, DbError>;
525
526 async fn set_recovery_token(
527 &self,
528 did: &Did,
529 token_hash: &str,
530 expires_at: DateTime<Utc>,
531 ) -> Result<(), DbError>;
532
533 async fn get_user_for_recovery(&self, did: &Did) -> Result<Option<UserForRecovery>, DbError>;
534
535 async fn get_accounts_scheduled_for_deletion(
536 &self,
537 limit: i64,
538 ) -> Result<Vec<ScheduledDeletionAccount>, DbError>;
539
540 async fn delete_account_with_firehose(&self, user_id: Uuid, did: &Did) -> Result<i64, DbError>;
541
542 async fn create_password_account(
543 &self,
544 input: &CreatePasswordAccountInput,
545 ) -> Result<CreatePasswordAccountResult, CreateAccountError>;
546
547 async fn create_delegated_account(
548 &self,
549 input: &CreateDelegatedAccountInput,
550 ) -> Result<Uuid, CreateAccountError>;
551
552 async fn create_passkey_account(
553 &self,
554 input: &CreatePasskeyAccountInput,
555 ) -> Result<CreatePasswordAccountResult, CreateAccountError>;
556
557 async fn create_sso_account(
558 &self,
559 input: &CreateSsoAccountInput,
560 ) -> Result<CreatePasswordAccountResult, CreateAccountError>;
561
562 async fn reactivate_migration_account(
563 &self,
564 input: &MigrationReactivationInput,
565 ) -> Result<ReactivatedAccountInfo, MigrationReactivationError>;
566
567 async fn check_handle_available_for_new_account(
568 &self,
569 handle: &Handle,
570 ) -> Result<bool, DbError>;
571
572 async fn reserve_handle(&self, handle: &Handle, reserved_by: &str) -> Result<bool, DbError>;
573
574 async fn release_handle_reservation(&self, handle: &Handle) -> Result<(), DbError>;
575
576 async fn cleanup_expired_handle_reservations(&self) -> Result<u64, DbError>;
577
578 async fn check_and_consume_invite_code(&self, code: &str) -> Result<bool, DbError>;
579
580 async fn complete_passkey_setup(
581 &self,
582 input: &CompletePasskeySetupInput,
583 ) -> Result<(), DbError>;
584
585 async fn recover_passkey_account(
586 &self,
587 input: &RecoverPasskeyAccountInput,
588 ) -> Result<RecoverPasskeyAccountResult, DbError>;
589
590 async fn get_password_reset_info(
591 &self,
592 email: &str,
593 ) -> Result<Option<crate::PasswordResetInfo>, DbError>;
594
595 async fn enable_totp_verified(&self, did: &Did, encrypted_secret: &[u8])
596 -> Result<(), DbError>;
597
598 async fn set_two_factor_enabled(&self, did: &Did, enabled: bool) -> Result<(), DbError>;
599
600 async fn expire_password_reset_code(&self, email: &str) -> Result<(), DbError>;
601}
602
603#[derive(Debug, Clone)]
604pub struct UserKeyWithId {
605 pub id: Uuid,
606 pub key_bytes: Vec<u8>,
607 pub encryption_version: Option<i32>,
608}
609
610#[derive(Debug, Clone)]
611pub struct UserKeyInfo {
612 pub key_bytes: Vec<u8>,
613 pub encryption_version: Option<i32>,
614}
615
616#[derive(Debug, Clone)]
617pub struct UserIdAndHandle {
618 pub id: Uuid,
619 pub handle: Handle,
620}
621
622#[derive(Debug, Clone)]
623pub struct UserDidWebInfo {
624 pub id: Uuid,
625 pub did: Did,
626 pub migrated_to_pds: Option<String>,
627}
628
629#[derive(Debug, Clone)]
630pub struct DidWebOverrides {
631 pub verification_methods: serde_json::Value,
632 pub also_known_as: Vec<String>,
633}
634
635#[derive(Debug, Clone)]
636pub struct UserCommsPrefs {
637 pub email: Option<String>,
638 pub handle: Handle,
639 pub preferred_channel: CommsChannel,
640 pub preferred_locale: Option<String>,
641 pub telegram_chat_id: Option<i64>,
642 pub discord_id: Option<String>,
643 pub signal_username: Option<String>,
644}
645
646#[derive(Debug, Clone)]
647pub struct UserForVerification {
648 pub id: Uuid,
649 pub did: Did,
650 pub email: Option<String>,
651 pub email_verified: bool,
652 pub handle: Handle,
653}
654
655#[derive(Debug, Clone)]
656pub struct OAuthTokenWithUser {
657 pub did: Did,
658 pub expires_at: DateTime<Utc>,
659 pub deactivated_at: Option<DateTime<Utc>>,
660 pub takedown_ref: Option<String>,
661 pub is_admin: bool,
662 pub key_bytes: Option<Vec<u8>>,
663 pub encryption_version: Option<i32>,
664}
665
666#[derive(Debug, Clone)]
667pub struct UserInfoForAuth {
668 pub deactivated_at: Option<DateTime<Utc>>,
669 pub takedown_ref: Option<String>,
670 pub is_admin: bool,
671 pub key_bytes: Option<Vec<u8>>,
672 pub encryption_version: Option<i32>,
673}
674
675#[derive(Debug, Clone)]
676pub struct AccountSearchResult {
677 pub did: Did,
678 pub handle: Handle,
679 pub email: Option<String>,
680 pub created_at: DateTime<Utc>,
681 pub email_verified: bool,
682 pub deactivated_at: Option<DateTime<Utc>>,
683 pub invites_disabled: Option<bool>,
684}
685
686#[derive(Debug, Clone)]
687pub struct UserAuthInfo {
688 pub id: Uuid,
689 pub did: Did,
690 pub password_hash: Option<String>,
691 pub deactivated_at: Option<DateTime<Utc>>,
692 pub takedown_ref: Option<String>,
693 pub channel_verification: ChannelVerificationStatus,
694}
695
696#[derive(Debug, Clone)]
697pub struct NotificationPrefs {
698 pub email: String,
699 pub preferred_channel: CommsChannel,
700 pub discord_id: Option<String>,
701 pub discord_username: Option<String>,
702 pub discord_verified: bool,
703 pub telegram_username: Option<String>,
704 pub telegram_verified: bool,
705 pub telegram_chat_id: Option<i64>,
706 pub signal_username: Option<String>,
707 pub signal_verified: bool,
708}
709
710#[derive(Debug, Clone)]
711pub struct UserIdHandleEmail {
712 pub id: Uuid,
713 pub handle: Handle,
714 pub email: Option<String>,
715}
716
717#[derive(Debug, Clone)]
718pub struct UserVerificationInfo {
719 pub id: Uuid,
720 pub handle: Handle,
721 pub email: Option<String>,
722 pub channel_verification: ChannelVerificationStatus,
723}
724
725#[derive(Debug, Clone)]
726pub struct StoredPasskey {
727 pub id: Uuid,
728 pub did: Did,
729 pub credential_id: Vec<u8>,
730 pub public_key: Vec<u8>,
731 pub sign_count: i32,
732 pub created_at: DateTime<Utc>,
733 pub last_used: Option<DateTime<Utc>>,
734 pub friendly_name: Option<String>,
735 pub aaguid: Option<Vec<u8>>,
736 pub transports: Option<Vec<String>>,
737}
738
739impl StoredPasskey {
740 pub fn credential_id_base64(&self) -> String {
741 use base64::{Engine, engine::general_purpose::URL_SAFE_NO_PAD};
742 URL_SAFE_NO_PAD.encode(&self.credential_id)
743 }
744}
745
746#[derive(Debug, Clone)]
747pub struct TotpRecord {
748 pub secret_encrypted: Vec<u8>,
749 pub encryption_version: i32,
750 pub verified: bool,
751}
752
753#[derive(Debug, Clone)]
754pub struct VerifiedTotpRecord {
755 pub secret_encrypted: Vec<u8>,
756 pub encryption_version: i32,
757}
758
759#[derive(Debug, Clone)]
760pub struct UnverifiedTotpRecord {
761 pub secret_encrypted: Vec<u8>,
762 pub encryption_version: i32,
763}
764
765#[derive(Debug, Clone)]
766pub enum TotpRecordState {
767 Verified(VerifiedTotpRecord),
768 Unverified(UnverifiedTotpRecord),
769}
770
771impl TotpRecordState {
772 pub fn is_verified(&self) -> bool {
773 matches!(self, Self::Verified(_))
774 }
775
776 pub fn as_verified(&self) -> Option<&VerifiedTotpRecord> {
777 match self {
778 Self::Verified(r) => Some(r),
779 Self::Unverified(_) => None,
780 }
781 }
782
783 pub fn as_unverified(&self) -> Option<&UnverifiedTotpRecord> {
784 match self {
785 Self::Unverified(r) => Some(r),
786 Self::Verified(_) => None,
787 }
788 }
789
790 pub fn into_verified(self) -> Option<VerifiedTotpRecord> {
791 match self {
792 Self::Verified(r) => Some(r),
793 Self::Unverified(_) => None,
794 }
795 }
796
797 pub fn into_unverified(self) -> Option<UnverifiedTotpRecord> {
798 match self {
799 Self::Unverified(r) => Some(r),
800 Self::Verified(_) => None,
801 }
802 }
803}
804
805impl From<TotpRecord> for TotpRecordState {
806 fn from(record: TotpRecord) -> Self {
807 if record.verified {
808 Self::Verified(VerifiedTotpRecord {
809 secret_encrypted: record.secret_encrypted,
810 encryption_version: record.encryption_version,
811 })
812 } else {
813 Self::Unverified(UnverifiedTotpRecord {
814 secret_encrypted: record.secret_encrypted,
815 encryption_version: record.encryption_version,
816 })
817 }
818 }
819}
820
821#[derive(Debug, Clone)]
822pub struct StoredBackupCode {
823 pub id: Uuid,
824 pub code_hash: String,
825}
826
827#[derive(Debug, Clone)]
828pub struct UserSessionInfo {
829 pub handle: Handle,
830 pub email: Option<String>,
831 pub is_admin: bool,
832 pub deactivated_at: Option<DateTime<Utc>>,
833 pub takedown_ref: Option<String>,
834 pub preferred_locale: Option<String>,
835 pub preferred_comms_channel: CommsChannel,
836 pub channel_verification: ChannelVerificationStatus,
837 pub migrated_to_pds: Option<String>,
838 pub migrated_at: Option<DateTime<Utc>>,
839 pub totp_enabled: bool,
840 pub email_2fa_enabled: bool,
841}
842
843#[derive(Debug, Clone)]
844pub struct UserLegacyLoginPref {
845 pub allow_legacy_login: bool,
846 pub has_mfa: bool,
847}
848
849#[derive(Debug, Clone)]
850pub struct UserLoginFull {
851 pub id: Uuid,
852 pub did: Did,
853 pub handle: Handle,
854 pub password_hash: Option<String>,
855 pub email: Option<String>,
856 pub deactivated_at: Option<DateTime<Utc>>,
857 pub takedown_ref: Option<String>,
858 pub channel_verification: ChannelVerificationStatus,
859 pub allow_legacy_login: bool,
860 pub migrated_to_pds: Option<String>,
861 pub preferred_comms_channel: CommsChannel,
862 pub key_bytes: Vec<u8>,
863 pub encryption_version: Option<i32>,
864 pub totp_enabled: bool,
865 pub email_2fa_enabled: bool,
866}
867
868#[derive(Debug, Clone)]
869pub struct UserConfirmSignup {
870 pub id: Uuid,
871 pub did: Did,
872 pub handle: Handle,
873 pub email: Option<String>,
874 pub channel: CommsChannel,
875 pub discord_username: Option<String>,
876 pub telegram_username: Option<String>,
877 pub signal_username: Option<String>,
878 pub key_bytes: Vec<u8>,
879 pub encryption_version: Option<i32>,
880}
881
882#[derive(Debug, Clone)]
883pub struct UserResendVerification {
884 pub id: Uuid,
885 pub handle: Handle,
886 pub email: Option<String>,
887 pub channel: CommsChannel,
888 pub discord_username: Option<String>,
889 pub telegram_username: Option<String>,
890 pub signal_username: Option<String>,
891 pub channel_verification: ChannelVerificationStatus,
892}
893
894#[derive(Debug, Clone)]
895pub struct UserResetCodeInfo {
896 pub id: Uuid,
897 pub did: Did,
898 pub preferred_comms_channel: CommsChannel,
899 pub expires_at: Option<DateTime<Utc>>,
900}
901
902#[derive(Debug, Clone)]
903pub struct UserPasswordInfo {
904 pub id: Uuid,
905 pub password_hash: Option<String>,
906}
907
908#[derive(Debug, Clone)]
909pub struct UserIdAndPasswordHash {
910 pub id: Uuid,
911 pub password_hash: String,
912}
913
914#[derive(Debug, Clone)]
915pub struct PasswordResetResult {
916 pub did: Did,
917 pub session_jtis: Vec<String>,
918}
919
920#[derive(Debug, Clone)]
921pub struct UserForDeletion {
922 pub id: Uuid,
923 pub password_hash: Option<String>,
924 pub handle: Handle,
925}
926
927#[derive(Debug, Clone)]
928pub struct ScheduledDeletionAccount {
929 pub id: Uuid,
930 pub did: Did,
931 pub handle: Handle,
932}
933
934#[derive(Debug, Clone)]
935pub struct UserForDidDoc {
936 pub id: Uuid,
937 pub handle: Handle,
938 pub deactivated_at: Option<DateTime<Utc>>,
939}
940
941#[derive(Debug, Clone)]
942pub struct UserForDidDocBuild {
943 pub id: Uuid,
944 pub handle: Handle,
945 pub migrated_to_pds: Option<String>,
946}
947
948#[derive(Debug, Clone)]
949pub struct UserForPasskeySetup {
950 pub id: Uuid,
951 pub handle: Handle,
952 pub recovery_token: Option<String>,
953 pub recovery_token_expires_at: Option<DateTime<Utc>>,
954 pub password_required: bool,
955}
956
957#[derive(Debug, Clone)]
958pub struct UserForPasskeyRecovery {
959 pub id: Uuid,
960 pub did: Did,
961 pub handle: Handle,
962 pub password_required: bool,
963}
964
965#[derive(Debug, Clone)]
966pub struct UserForRecovery {
967 pub id: Uuid,
968 pub did: Did,
969 pub preferred_comms_channel: CommsChannel,
970 pub recovery_token: Option<String>,
971 pub recovery_token_expires_at: Option<DateTime<Utc>>,
972}
973
974#[derive(Debug, Clone)]
975pub struct CreatePasswordAccountInput {
976 pub handle: Handle,
977 pub email: Option<String>,
978 pub did: Did,
979 pub password_hash: String,
980 pub preferred_comms_channel: CommsChannel,
981 pub discord_username: Option<String>,
982 pub telegram_username: Option<String>,
983 pub signal_username: Option<String>,
984 pub deactivated_at: Option<DateTime<Utc>>,
985 pub encrypted_key_bytes: Vec<u8>,
986 pub encryption_version: i32,
987 pub reserved_key_id: Option<Uuid>,
988 pub commit_cid: String,
989 pub repo_rev: String,
990 pub genesis_block_cids: Vec<Vec<u8>>,
991 pub invite_code: Option<String>,
992 pub birthdate_pref: Option<serde_json::Value>,
993}
994
995#[derive(Debug, Clone, Default)]
996pub struct CreatePasswordAccountResult {
997 pub user_id: Uuid,
998 pub is_admin: bool,
999}
1000
1001#[derive(Debug, Clone)]
1002pub enum CreateAccountError {
1003 HandleTaken,
1004 EmailTaken,
1005 DidExists,
1006 InvalidToken,
1007 Database(String),
1008}
1009
1010#[derive(Debug, Clone)]
1011pub struct CreateDelegatedAccountInput {
1012 pub handle: Handle,
1013 pub email: Option<String>,
1014 pub did: Did,
1015 pub controller_did: Did,
1016 pub controller_scopes: String,
1017 pub encrypted_key_bytes: Vec<u8>,
1018 pub encryption_version: i32,
1019 pub commit_cid: String,
1020 pub repo_rev: String,
1021 pub genesis_block_cids: Vec<Vec<u8>>,
1022 pub invite_code: Option<String>,
1023}
1024
1025#[derive(Debug, Clone)]
1026pub struct CreatePasskeyAccountInput {
1027 pub handle: Handle,
1028 pub email: String,
1029 pub did: Did,
1030 pub preferred_comms_channel: CommsChannel,
1031 pub discord_username: Option<String>,
1032 pub telegram_username: Option<String>,
1033 pub signal_username: Option<String>,
1034 pub setup_token_hash: String,
1035 pub setup_expires_at: DateTime<Utc>,
1036 pub deactivated_at: Option<DateTime<Utc>>,
1037 pub encrypted_key_bytes: Vec<u8>,
1038 pub encryption_version: i32,
1039 pub reserved_key_id: Option<Uuid>,
1040 pub commit_cid: String,
1041 pub repo_rev: String,
1042 pub genesis_block_cids: Vec<Vec<u8>>,
1043 pub invite_code: Option<String>,
1044 pub birthdate_pref: Option<serde_json::Value>,
1045}
1046
1047#[derive(Debug, Clone)]
1048pub struct CreateSsoAccountInput {
1049 pub handle: Handle,
1050 pub email: Option<String>,
1051 pub did: Did,
1052 pub preferred_comms_channel: CommsChannel,
1053 pub discord_username: Option<String>,
1054 pub telegram_username: Option<String>,
1055 pub signal_username: Option<String>,
1056 pub encrypted_key_bytes: Vec<u8>,
1057 pub encryption_version: i32,
1058 pub commit_cid: String,
1059 pub repo_rev: String,
1060 pub genesis_block_cids: Vec<Vec<u8>>,
1061 pub invite_code: Option<String>,
1062 pub birthdate_pref: Option<serde_json::Value>,
1063 pub sso_provider: SsoProviderType,
1064 pub sso_provider_user_id: String,
1065 pub sso_provider_username: Option<String>,
1066 pub sso_provider_email: Option<String>,
1067 pub sso_provider_email_verified: bool,
1068 pub pending_registration_token: String,
1069}
1070
1071#[derive(Debug, Clone)]
1072pub struct CompletePasskeySetupInput {
1073 pub user_id: Uuid,
1074 pub did: Did,
1075 pub app_password_name: String,
1076 pub app_password_hash: String,
1077}
1078
1079#[derive(Debug, Clone)]
1080pub struct RecoverPasskeyAccountInput {
1081 pub did: Did,
1082 pub password_hash: String,
1083}
1084
1085#[derive(Debug, Clone)]
1086pub struct RecoverPasskeyAccountResult {
1087 pub passkeys_deleted: u64,
1088}
1089
1090#[derive(Debug, Clone)]
1091pub struct MigrationReactivationInput {
1092 pub did: Did,
1093 pub new_handle: Handle,
1094 pub new_email: Option<String>,
1095}
1096
1097#[derive(Debug, Clone)]
1098pub struct ReactivatedAccountInfo {
1099 pub user_id: Uuid,
1100 pub old_handle: Handle,
1101}
1102
1103#[derive(Debug, Clone)]
1104pub enum MigrationReactivationError {
1105 NotFound,
1106 NotDeactivated,
1107 HandleTaken,
1108 Database(String),
1109}