1use thiserror::Error;
3
4use crate::entry::ID;
5
6#[derive(Error, Debug)]
7pub enum UserError {
8 #[error("User not found: {username}")]
9 UserNotFound { username: String },
10
11 #[error("Username already exists: {username}")]
12 UsernameAlreadyExists { username: String },
13
14 #[error(
15 "Multiple users detected with username '{username}' ({count} found). This indicates a race condition during user creation. Manual intervention required."
16 )]
17 DuplicateUsersDetected { username: String, count: usize },
18
19 #[error("Invalid password")]
20 InvalidPassword,
21
22 #[error("Key not found: {key_id}")]
23 KeyNotFound { key_id: String },
24
25 #[error("Key already exists: {key_id}")]
26 KeyAlreadyExists { key_id: String },
27
28 #[error("Encryption failed: {reason}")]
29 EncryptionFailed { reason: String },
30
31 #[error("Decryption failed: {reason}")]
32 DecryptionFailed { reason: String },
33
34 #[error("Operation requires admin permission")]
35 InsufficientPermissions,
36
37 #[error("No admin key available for database: {database_id}")]
38 NoAdminKey { database_id: ID },
39
40 #[error("Database not tracked: {database_id}")]
41 DatabaseNotTracked { database_id: ID },
42
43 #[error("Database not found by name: {name}")]
44 DatabaseNotFoundByName { name: String },
45
46 #[error("User account disabled: {username}")]
47 UserDisabled { username: String },
48
49 #[error("Invalid salt length: expected {expected}, got {actual}")]
50 InvalidSaltLength { expected: usize, actual: usize },
51
52 #[error("Invalid nonce length: expected {expected}, got {actual}")]
53 InvalidNonceLength { expected: usize, actual: usize },
54
55 #[error("No key found for database: {database_id}")]
56 NoKeyForDatabase { database_id: ID },
57
58 #[error("No SigKey mapping found for key {key_id} in database {database_id}")]
59 NoSigKeyMapping { key_id: String, database_id: ID },
60
61 #[error("No SigKey found for key {key_id} in database {database_id}")]
62 NoSigKeyFound { key_id: String, database_id: ID },
63
64 #[error(
65 "Database access pending for {database_id}: a key mapping exists but the database has no local data yet \
66 (the bootstrap request may be awaiting approval, or the database has not synced)"
67 )]
68 DatabaseAccessPending { database_id: ID },
69
70 #[error("Password required for operation: {operation}")]
71 PasswordRequired { operation: String },
72
73 #[error("Invalid key format: {reason}")]
74 InvalidKeyFormat { reason: String },
75
76 #[error("No keys available for user")]
77 NoKeysAvailable,
78
79 #[error("Duplicate store name in DatabaseBuilder: {name}")]
80 DuplicateBuilderStore { name: String },
81}
82
83impl UserError {
84 pub fn is_not_found(&self) -> bool {
86 matches!(
87 self,
88 UserError::UserNotFound { .. }
89 | UserError::KeyNotFound { .. }
90 | UserError::DatabaseNotTracked { .. }
91 | UserError::DatabaseNotFoundByName { .. }
92 )
93 }
94}