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