kanidm_proto/internal/
error.rs

1use std::fmt::{Display, Formatter};
2
3use serde::{Deserialize, Serialize};
4use utoipa::ToSchema;
5use uuid::Uuid;
6
7use super::credupdate::PasswordFeedback;
8use crate::attribute::Attribute;
9
10/* ===== errors ===== */
11#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, ToSchema)]
12#[serde(rename_all = "lowercase")]
13pub enum SchemaError {
14    NotImplemented,
15    NoClassFound,
16    InvalidClass(Vec<String>),
17    MissingMustAttribute(Vec<Attribute>),
18    InvalidAttribute(String),
19    InvalidAttributeSyntax(String),
20    AttributeNotValidForClass(String),
21    SupplementsNotSatisfied(Vec<String>),
22    ExcludesNotSatisfied(Vec<String>),
23    EmptyFilter,
24    Corrupted,
25    PhantomAttribute(String),
26}
27
28#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, ToSchema)]
29#[serde(rename_all = "lowercase")]
30pub enum PluginError {
31    AttrUnique(String),
32    Base(String),
33    ReferentialIntegrity(String),
34    CredImport(String),
35    Oauth2Secrets,
36}
37
38#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, ToSchema)]
39#[serde(rename_all = "lowercase")]
40pub enum ConsistencyError {
41    Unknown,
42    // Class, Attribute
43    SchemaClassMissingAttribute(String, String),
44    SchemaClassPhantomAttribute(String, String),
45    SchemaUuidNotUnique(Uuid),
46    QueryServerSearchFailure,
47    EntryUuidCorrupt(u64),
48    UuidIndexCorrupt(String),
49    UuidNotUnique(String),
50    RefintNotUpheld(u64),
51    MemberOfInvalid(u64),
52    InvalidAttributeType(String),
53    DuplicateUniqueAttribute,
54    InvalidSpn(u64),
55    SqliteIntegrityFailure,
56    BackendAllIdsSync,
57    BackendIndexSync,
58    ChangelogDesynchronised(u64),
59    ChangeStateDesynchronised(u64),
60    RuvInconsistent(String),
61    DeniedName(Uuid),
62    KeyProviderUuidMissing { key_object: Uuid },
63    KeyProviderNoKeys { key_object: Uuid },
64    KeyProviderNotFound { key_object: Uuid, provider: Uuid },
65}
66
67#[derive(Serialize, Deserialize, Debug, ToSchema)]
68#[serde(rename_all = "lowercase")]
69pub enum OperationError {
70    // Logic errors, or "soft" errors.
71    SessionExpired,
72    DuplicateKey,
73    DuplicateLabel,
74    EmptyRequest,
75    Backend,
76    NoMatchingEntries,
77    NoMatchingAttributes,
78    UniqueConstraintViolation,
79    CorruptedEntry(u64),
80    CorruptedIndex(String),
81    ConsistencyError(Vec<ConsistencyError>),
82    SchemaViolation(SchemaError),
83    Plugin(PluginError),
84    FilterGeneration,
85    FilterParseError,
86    FilterUuidResolution,
87    InvalidAttributeName(String),
88    InvalidAttribute(String),
89    InvalidLabel,
90    InvalidDbState,
91    InvalidCacheState,
92    InvalidValueState,
93    InvalidEntryId,
94    InvalidRequestState,
95    InvalidSyncState,
96    InvalidState,
97    InvalidEntryState,
98    InvalidUuid,
99    InvalidReplChangeId,
100    InvalidAcpState(String),
101    InvalidSchemaState(String),
102    InvalidAccountState(String),
103    // This really oughta be EntryClass but its not in proto...
104    // It should at least be &'static str but we
105    // Serialize & Deserialize this enum...
106    MissingClass(String),
107    MissingAttribute(Attribute),
108    MissingEntries,
109    ModifyAssertionFailed,
110    BackendEngine,
111    SqliteError, //(RusqliteError)
112    FsError,
113    SerdeJsonError,
114    SerdeCborError,
115    AccessDenied,
116    NotAuthenticated,
117    NotAuthorised,
118    InvalidAuthState(String),
119    InvalidSessionState,
120    SystemProtectedObject,
121    SystemProtectedAttribute,
122    PasswordQuality(Vec<PasswordFeedback>),
123    CryptographyError,
124    ResourceLimit,
125    QueueDisconnected,
126    Webauthn,
127    #[serde(with = "time::serde::timestamp")]
128    Wait(time::OffsetDateTime),
129    ReplReplayFailure,
130    ReplEntryNotChanged,
131    ReplInvalidRUVState,
132    ReplDomainLevelUnsatisfiable,
133    ReplDomainUuidMismatch,
134    ReplServerUuidSplitDataState,
135    TransactionAlreadyCommitted,
136    CannotStartMFADuringOngoingMFASession,
137    /// when you ask for a gid that overlaps a system reserved range
138    /// When a name is denied by the system config
139    ValueDenyName,
140    /// When the DB is potentially over-loaded a timeout can occur starting
141    /// your operation.
142    DatabaseLockAcquisitionTimeout,
143
144    // Specific internal errors.
145    AU0001InvalidState,
146    AU0002JwsSerialisation,
147    AU0003JwsSignature,
148    AU0004UserAuthTokenInvalid,
149    AU0005DelayedProcessFailure,
150    AU0006CredentialMayNotReauthenticate,
151    AU0007UserAuthTokenInvalid,
152    AU0008ClientAuthInfoPrevalidation,
153
154    // Kanidm Generic Errors
155    KG001TaskTimeout,
156    KG002TaskCommFailure,
157    KG003CacheClearFailed,
158
159    // Credential Update Errors
160    CU0001WebauthnAttestationNotTrusted,
161    CU0002WebauthnRegistrationError,
162    CU0003WebauthnUserNotVerified,
163
164    // The session is inconsistent and can't be committed, but the errors
165    // can be resolved.
166    CU0004SessionInconsistent,
167    // Another session used this intent token, and so it can't be committed.
168    CU0005IntentTokenConflict,
169    // The intent token was invalidated before we could commit.
170    CU0006IntentTokenInvalidated,
171
172    // ValueSet errors
173    VS0001IncomingReplSshPublicKey,
174    VS0002CertificatePublicKeyDigest,
175    VS0003CertificateDerDecode,
176    VS0004CertificatePublicKeyDigest,
177    VS0005CertificatePublicKeyDigest,
178    // Value Errors
179    VL0001ValueSshPublicKeyString,
180
181    // LDAP Errors
182    LD0001AnonymousNotAllowed,
183
184    // DB low level errors.
185    DB0001MismatchedRestoreVersion,
186    DB0002MismatchedRestoreVersion,
187    DB0003FilterResolveCacheBuild,
188    DB0004DatabaseTooOld,
189
190    // SCIM
191    SC0001IncomingSshPublicKey,
192    SC0002ReferenceSyntaxInvalid,
193    SC0003MailSyntaxInvalid,
194    SC0004UuidSyntaxInvalid,
195    SC0005BoolSyntaxInvalid,
196    SC0006Uint32SyntaxInvalid,
197    SC0007UrlSyntaxInvalid,
198    SC0008SyntaxTypeSyntaxInvalid,
199    SC0009IndexTypeSyntaxInvalid,
200    SC0010DateTimeSyntaxInvalid,
201    SC0011AddressSyntaxInvalid,
202    SC0012CertificateSyntaxInvalid,
203    SC0013CertificateInvalidDer,
204    SC0014CertificateInvalidDigest,
205    SC0015CredentialTypeSyntaxInvalid,
206    SC0016InameSyntaxInvalid,
207    SC0017Iutf8SyntaxInvalid,
208    SC0018NsUniqueIdSyntaxInvalid,
209    SC0019Oauth2ScopeSyntaxInvalid,
210    SC0020Oauth2ScopeMapSyntaxInvalid,
211    SC0021Oauth2ScopeMapMissingGroupIdentifier,
212    SC0022Oauth2ClaimMapSyntaxInvalid,
213    SC0023Oauth2ClaimMapMissingGroupIdentifier,
214    SC0024SshPublicKeySyntaxInvalid,
215    SC0025UiHintSyntaxInvalid,
216    SC0026Utf8SyntaxInvalid,
217    SC0027ClassSetInvalid,
218    SC0028CreatedUuidsInvalid,
219    SC0029PaginationOutOfBounds,
220    // Migration
221    MG0001InvalidReMigrationLevel,
222    MG0002RaiseDomainLevelExceedsMaximum,
223    MG0003ServerPhaseInvalidForMigration,
224    MG0004DomainLevelInDevelopment,
225    MG0005GidConstraintsNotMet,
226    MG0006SKConstraintsNotMet,
227    MG0007Oauth2StrictConstraintsNotMet,
228    MG0008SkipUpgradeAttempted,
229    MG0009InvalidTargetLevelForBootstrap,
230    //
231    KP0001KeyProviderNotLoaded,
232    KP0002KeyProviderInvalidClass,
233    KP0003KeyProviderInvalidType,
234    KP0004KeyProviderMissingAttributeName,
235    KP0005KeyProviderDuplicate,
236    KP0006KeyObjectJwtEs256Generation,
237    KP0007KeyProviderDefaultNotAvailable,
238    KP0008KeyObjectMissingUuid,
239    KP0009KeyObjectPrivateToDer,
240    KP0010KeyObjectSignerToVerifier,
241    KP0011KeyObjectMissingClass,
242    KP0012KeyObjectMissingProvider,
243    KP0012KeyProviderNotLoaded,
244    KP0013KeyObjectJwsEs256DerInvalid,
245    KP0014KeyObjectSignerToVerifier,
246    KP0015KeyObjectJwsEs256DerInvalid,
247    KP0016KeyObjectJwsEs256DerInvalid,
248    KP0017KeyProviderNoSuchKey,
249    KP0018KeyProviderNoSuchKey,
250    KP0019KeyProviderUnsupportedAlgorithm,
251    KP0020KeyObjectNoActiveSigningKeys,
252    KP0021KeyObjectJwsEs256Signature,
253    KP0022KeyObjectJwsNotAssociated,
254    KP0023KeyObjectJwsKeyRevoked,
255    KP0024KeyObjectJwsInvalid,
256    KP0025KeyProviderNotAvailable,
257    KP0026KeyObjectNoSuchKey,
258    KP0027KeyObjectPublicToDer,
259    KP0028KeyObjectImportJwsEs256DerInvalid,
260    KP0029KeyObjectSignerToVerifier,
261    KP0030KeyObjectPublicToDer,
262    KP0031KeyObjectNotFound,
263    KP0032KeyProviderNoSuchKey,
264    KP0033KeyProviderNoSuchKey,
265    KP0034KeyProviderUnsupportedAlgorithm,
266    KP0035KeyObjectJweA128GCMGeneration,
267    KP0036KeyObjectPrivateToBytes,
268    KP0037KeyObjectImportJweA128GCMInvalid,
269    KP0038KeyObjectImportJweA128GCMInvalid,
270    KP0039KeyObjectJweNotAssociated,
271    KP0040KeyObjectJweInvalid,
272    KP0041KeyObjectJweRevoked,
273    KP0042KeyObjectNoActiveEncryptionKeys,
274    KP0043KeyObjectJweA128GCMEncryption,
275    KP0044KeyObjectJwsPublicJwk,
276
277    KP0045KeyObjectImportJwsRs256DerInvalid,
278    KP0046KeyObjectSignerToVerifier,
279    KP0047KeyObjectPublicToDer,
280    KP0048KeyObjectJwtRs256Generation,
281    KP0049KeyObjectSignerToVerifier,
282    KP0050KeyObjectPrivateToDer,
283    KP0051KeyObjectPublicToDer,
284    KP0052KeyObjectJwsRs256DerInvalid,
285    KP0053KeyObjectSignerToVerifier,
286    KP0054KeyObjectJwsRs256DerInvalid,
287    KP0055KeyObjectJwsRs256DerInvalid,
288    KP0056KeyObjectJwsRs256Signature,
289    KP0057KeyObjectJwsNotAssociated,
290    KP0058KeyObjectJwsInvalid,
291    KP0059KeyObjectJwsKeyRevoked,
292    KP0060KeyObjectJwsPublicJwk,
293    KP0061KeyObjectNoActiveSigningKeys,
294    KP0062KeyProviderNoSuchKey,
295
296    KP0063KeyObjectJwsHs256DerInvalid,
297    KP0064KeyObjectSignerToVerifier,
298    KP0065KeyObjectJwtHs256Generation,
299    KP0066KeyObjectJwsHs256DerInvalid,
300    KP0067KeyObjectSignerToVerifier,
301    KP0068KeyObjectJwsHs256DerInvalid,
302    KP0069KeyObjectNoActiveSigningKeys,
303    KP0070KeyObjectJwsHs256Signature,
304    KP0071KeyObjectPrivateToDer,
305
306    // Plugins
307    PL0001GidOverlapsSystemRange,
308
309    // Web UI
310    UI0001ChallengeSerialisation,
311    UI0002InvalidState,
312    UI0003InvalidOauth2Resume,
313
314    // Unixd Things
315    KU001InitWhileSessionActive,
316    KU002ContinueWhileSessionInActive,
317    KU003PamAuthFailed,
318    KU004PamInitFailed,
319    KU005ErrorCheckingAccount,
320    KU006OnlyRootAllowed,
321}
322
323impl PartialEq for OperationError {
324    fn eq(&self, other: &Self) -> bool {
325        // We do this to avoid InvalidPassword being checked as it's not
326        // derive PartialEq. Generally we only use the PartialEq for TESTING
327        // anyway.
328        std::mem::discriminant(self) == std::mem::discriminant(other)
329    }
330}
331
332impl Display for OperationError {
333    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
334        let mut output = format!("{self:?}")
335            .split("::")
336            .last()
337            .unwrap_or("")
338            .to_string();
339
340        if let Some(msg) = self.message() {
341            output += &format!(" - {msg}");
342        };
343        f.write_str(&output)
344    }
345}
346
347impl OperationError {
348    /// Return the message associated with the error if there is one.
349    pub fn message(&self) -> Option<String> {
350        match self {
351            Self::SessionExpired => None,
352            Self::EmptyRequest => None,
353            Self::Backend => None,
354            Self::NoMatchingEntries => None,
355            Self::NoMatchingAttributes => None,
356            Self::UniqueConstraintViolation => Some("A unique constraint was violated resulting in multiple conflicting results.".into()),
357            Self::CorruptedEntry(_) => None,
358            Self::CorruptedIndex(_) => None,
359            Self::ConsistencyError(_) => None,
360            Self::SchemaViolation(_) => None,
361            Self::Plugin(_) => None,
362            Self::FilterGeneration => None,
363            Self::FilterParseError => None,
364            Self::FilterUuidResolution => None,
365            Self::InvalidAttributeName(_) => None,
366            Self::InvalidAttribute(_) => None,
367            Self::InvalidLabel => Some("The submitted label for this item is invalid.".into()),
368            Self::DuplicateLabel => Some("The submitted label for this item is already in use.".into()),
369            Self::DuplicateKey => Some("The submitted key already exists.".into()),
370            Self::InvalidDbState => None,
371            Self::InvalidCacheState => None,
372            Self::InvalidValueState => None,
373            Self::InvalidEntryId => None,
374            Self::InvalidRequestState => None,
375            Self::InvalidSyncState => None,
376            Self::InvalidState => None,
377            Self::InvalidEntryState => None,
378            Self::InvalidUuid => None,
379            Self::InvalidReplChangeId => None,
380            Self::InvalidAcpState(_) => None,
381            Self::InvalidSchemaState(_) => None,
382            Self::InvalidAccountState(val) => Some(format!("Invalid account state: {val}")),
383            Self::MissingClass(val) => Some(format!("Missing class: {val}")),
384            Self::MissingAttribute(val) => Some(format!("Missing attribute: {val}")),
385            Self::MissingEntries => None,
386            Self::ModifyAssertionFailed => None,
387            Self::BackendEngine => None,
388            Self::SqliteError => None,
389            Self::FsError => None,
390            Self::SerdeJsonError => None,
391            Self::SerdeCborError => None,
392            Self::AccessDenied => None,
393            Self::NotAuthenticated => None,
394            Self::NotAuthorised => None,
395            Self::InvalidAuthState(_) => None,
396            Self::InvalidSessionState => None,
397            Self::SystemProtectedObject => None,
398            Self::SystemProtectedAttribute => None,
399            Self::PasswordQuality(_) => None,
400            Self::CryptographyError => None,
401            Self::ResourceLimit => None,
402            Self::QueueDisconnected => None,
403            Self::Webauthn => None,
404            Self::Wait(_) => None,
405            Self::CannotStartMFADuringOngoingMFASession => Some("Cannot start a new MFA authentication flow when there already is one active.".into()),
406            Self::ReplReplayFailure => None,
407            Self::ReplEntryNotChanged => None,
408            Self::ReplInvalidRUVState => None,
409            Self::ReplDomainLevelUnsatisfiable => None,
410            Self::ReplDomainUuidMismatch => None,
411            Self::ReplServerUuidSplitDataState => None,
412            Self::TransactionAlreadyCommitted => None,
413            Self::ValueDenyName => None,
414            Self::DatabaseLockAcquisitionTimeout => Some("Unable to acquire a database lock - the current server may be too busy. Try again later.".into()),
415
416    Self::AU0001InvalidState => Some("Invalid authentication session state for request".into()),
417    Self::AU0002JwsSerialisation => Some("JWS serialisation failed".into()),
418    Self::AU0003JwsSignature => Some("JWS signature failed".into()),
419    Self::AU0004UserAuthTokenInvalid => Some("User auth token was unable to be generated".into()),
420    Self::AU0005DelayedProcessFailure => Some("Delaying processing failure, unable to proceed".into()),
421    Self::AU0006CredentialMayNotReauthenticate => Some("Credential may not reauthenticate".into()),
422    Self::AU0007UserAuthTokenInvalid => Some("User auth token was unable to be generated".into()),
423    Self::AU0008ClientAuthInfoPrevalidation => Some("Client Authentication Info prevalidation did not occur when expected".into()),
424
425            Self::CU0001WebauthnAttestationNotTrusted => None,
426            Self::CU0002WebauthnRegistrationError => None,
427            Self::CU0003WebauthnUserNotVerified => Some("User Verification bit not set while registering credential, you may need to configure a PIN on this device.".into()),
428
429            Self::CU0004SessionInconsistent => Some("The session is unable to be committed due to unresolved warnings.".into()),
430            Self::CU0005IntentTokenConflict => Some("The intent token used to create this session has been reused in another browser/tab and may not proceed.".into()),
431            Self::CU0006IntentTokenInvalidated => Some("The intent token has been invalidated/revoked before the commit could be accepted. Has it been used in another browser or tab?".into()),
432
433            Self::DB0001MismatchedRestoreVersion => None,
434            Self::DB0002MismatchedRestoreVersion => None,
435            Self::DB0003FilterResolveCacheBuild => None,
436            Self::DB0004DatabaseTooOld => Some("The database is too old to be migrated.".into()),
437            Self::KG001TaskTimeout => Some("Task timed out".into()),
438            Self::KG002TaskCommFailure => Some("Inter-Task communication failure".into()),
439            Self::KG003CacheClearFailed => Some("Failed to clear cache".into()),
440            Self::KP0001KeyProviderNotLoaded => None,
441            Self::KP0002KeyProviderInvalidClass => None,
442            Self::KP0003KeyProviderInvalidType => None,
443            Self::KP0004KeyProviderMissingAttributeName => None,
444            Self::KP0005KeyProviderDuplicate => None,
445            Self::KP0006KeyObjectJwtEs256Generation => None,
446            Self::KP0007KeyProviderDefaultNotAvailable => None,
447            Self::KP0008KeyObjectMissingUuid => None,
448            Self::KP0009KeyObjectPrivateToDer => None,
449            Self::KP0010KeyObjectSignerToVerifier => None,
450            Self::KP0011KeyObjectMissingClass => None,
451            Self::KP0012KeyObjectMissingProvider => None,
452            Self::KP0012KeyProviderNotLoaded => None,
453            Self::KP0013KeyObjectJwsEs256DerInvalid => None,
454            Self::KP0014KeyObjectSignerToVerifier => None,
455            Self::KP0015KeyObjectJwsEs256DerInvalid => None,
456            Self::KP0016KeyObjectJwsEs256DerInvalid => None,
457            Self::KP0017KeyProviderNoSuchKey => None,
458            Self::KP0018KeyProviderNoSuchKey => None,
459            Self::KP0019KeyProviderUnsupportedAlgorithm => None,
460            Self::KP0020KeyObjectNoActiveSigningKeys => None,
461            Self::KP0021KeyObjectJwsEs256Signature => None,
462            Self::KP0022KeyObjectJwsNotAssociated => None,
463            Self::KP0023KeyObjectJwsKeyRevoked => None,
464            Self::KP0024KeyObjectJwsInvalid => None,
465            Self::KP0025KeyProviderNotAvailable => None,
466            Self::KP0026KeyObjectNoSuchKey => None,
467            Self::KP0027KeyObjectPublicToDer => None,
468            Self::KP0028KeyObjectImportJwsEs256DerInvalid => None,
469            Self::KP0029KeyObjectSignerToVerifier => None,
470            Self::KP0030KeyObjectPublicToDer => None,
471            Self::KP0031KeyObjectNotFound => None,
472            Self::KP0032KeyProviderNoSuchKey => None,
473            Self::KP0033KeyProviderNoSuchKey => None,
474            Self::KP0034KeyProviderUnsupportedAlgorithm => None,
475            Self::KP0035KeyObjectJweA128GCMGeneration => None,
476            Self::KP0036KeyObjectPrivateToBytes => None,
477            Self::KP0037KeyObjectImportJweA128GCMInvalid => None,
478            Self::KP0038KeyObjectImportJweA128GCMInvalid => None,
479            Self::KP0039KeyObjectJweNotAssociated => None,
480            Self::KP0040KeyObjectJweInvalid => None,
481            Self::KP0041KeyObjectJweRevoked => None,
482            Self::KP0042KeyObjectNoActiveEncryptionKeys => None,
483            Self::KP0043KeyObjectJweA128GCMEncryption => None,
484            Self::KP0044KeyObjectJwsPublicJwk => None,
485
486            Self::KP0045KeyObjectImportJwsRs256DerInvalid => None,
487            Self::KP0046KeyObjectSignerToVerifier => None,
488            Self::KP0047KeyObjectPublicToDer => None,
489            Self::KP0048KeyObjectJwtRs256Generation => None,
490            Self::KP0049KeyObjectSignerToVerifier => None,
491            Self::KP0050KeyObjectPrivateToDer => None,
492            Self::KP0051KeyObjectPublicToDer => None,
493            Self::KP0052KeyObjectJwsRs256DerInvalid => None,
494            Self::KP0053KeyObjectSignerToVerifier => None,
495            Self::KP0054KeyObjectJwsRs256DerInvalid => None,
496            Self::KP0055KeyObjectJwsRs256DerInvalid => None,
497            Self::KP0056KeyObjectJwsRs256Signature => None,
498            Self::KP0057KeyObjectJwsNotAssociated => None,
499            Self::KP0058KeyObjectJwsInvalid => None,
500            Self::KP0059KeyObjectJwsKeyRevoked => None,
501            Self::KP0060KeyObjectJwsPublicJwk => None,
502            Self::KP0061KeyObjectNoActiveSigningKeys => None,
503            Self::KP0062KeyProviderNoSuchKey => None,
504
505            Self::KP0063KeyObjectJwsHs256DerInvalid => None,
506            Self::KP0064KeyObjectSignerToVerifier => None,
507            Self::KP0065KeyObjectJwtHs256Generation => None,
508
509            Self::KP0066KeyObjectJwsHs256DerInvalid => None,
510            Self::KP0067KeyObjectSignerToVerifier => None,
511            Self::KP0068KeyObjectJwsHs256DerInvalid => None,
512            Self::KP0069KeyObjectNoActiveSigningKeys => None,
513            Self::KP0070KeyObjectJwsHs256Signature => None,
514            Self::KP0071KeyObjectPrivateToDer => None,
515
516
517            Self::KU001InitWhileSessionActive => Some("The session was active when the init function was called.".into()),
518            Self::KU002ContinueWhileSessionInActive => Some("Attempted to continue auth session while current session is inactive".into()),
519            Self::KU003PamAuthFailed => Some("Failed PAM account authentication step".into()),
520            Self::KU004PamInitFailed => Some("Failed to initialise PAM authentication".into()),
521            Self::KU005ErrorCheckingAccount => Some("Error checking account".into()),
522            Self::KU006OnlyRootAllowed => Some("Only root is allowed to perform this operation".into()),
523            Self::LD0001AnonymousNotAllowed => Some("Anonymous is not allowed to access LDAP with this method.".into()),
524            Self::MG0001InvalidReMigrationLevel => None,
525            Self::MG0002RaiseDomainLevelExceedsMaximum => None,
526            Self::MG0003ServerPhaseInvalidForMigration => None,
527            Self::MG0004DomainLevelInDevelopment => None,
528            Self::MG0005GidConstraintsNotMet => None,
529            Self::MG0006SKConstraintsNotMet => Some("Migration Constraints Not Met - Security Keys should not be present.".into()),
530            Self::MG0007Oauth2StrictConstraintsNotMet => Some("Migration Constraints Not Met - All OAuth2 clients must have strict-redirect-uri mode enabled.".into()),
531            Self::MG0008SkipUpgradeAttempted => Some("Skip Upgrade Attempted.".into()),
532            Self::MG0009InvalidTargetLevelForBootstrap => Some("The request target domain level was not valid for bootstrapping a new server instance".into()),
533            Self::PL0001GidOverlapsSystemRange => None,
534            Self::SC0001IncomingSshPublicKey => None,
535            Self::SC0002ReferenceSyntaxInvalid => Some("A SCIM Reference Set contained invalid syntax and can not be processed.".into()),
536            Self::SC0003MailSyntaxInvalid => Some("A SCIM Mail Address contained invalid syntax".into()),
537            Self::SC0004UuidSyntaxInvalid => Some("A SCIM Uuid contained invalid syntax".into()),
538            Self::SC0005BoolSyntaxInvalid => Some("A SCIM boolean contained invalid syntax".into()),
539            Self::SC0006Uint32SyntaxInvalid => Some("A SCIM Uint32 contained invalid syntax".into()),
540            Self::SC0007UrlSyntaxInvalid => Some("A SCIM Url contained invalid syntax".into()),
541            Self::SC0008SyntaxTypeSyntaxInvalid => Some("A SCIM SyntaxType contained invalid syntax".into()),
542            Self::SC0009IndexTypeSyntaxInvalid => Some("A SCIM IndexType contained invalid syntax".into()),
543            Self::SC0010DateTimeSyntaxInvalid => Some("A SCIM DateTime contained invalid syntax".into()),
544
545            Self::SC0011AddressSyntaxInvalid => Some("A SCIM Address contained invalid syntax".into()),
546            Self::SC0012CertificateSyntaxInvalid => Some("A SCIM Certificate contained invalid binary data".into()),
547            Self::SC0013CertificateInvalidDer => Some("A SCIM Certificate did not contain valid DER".into()),
548            Self::SC0014CertificateInvalidDigest => Some("A SCIM Certificate was unable to be digested".into()),
549            Self::SC0015CredentialTypeSyntaxInvalid => Some("A SCIM CredentialType contained invalid syntax".into()),
550            Self::SC0016InameSyntaxInvalid => Some("A SCIM Iname string contained invalid syntax".into()),
551            Self::SC0017Iutf8SyntaxInvalid => Some("A SCIM Iutf8 string contained invalid syntax".into()),
552            Self::SC0018NsUniqueIdSyntaxInvalid => Some("A SCIM NsUniqueID contained invalid syntax".into()),
553            Self::SC0019Oauth2ScopeSyntaxInvalid => Some("A SCIM Oauth2 Scope contained invalid syntax".into()),
554            Self::SC0020Oauth2ScopeMapSyntaxInvalid => Some("A SCIM Oauth2 Scope Map contained invalid syntax".into()),
555            Self::SC0021Oauth2ScopeMapMissingGroupIdentifier => Some("A SCIM Oauth2 Scope Map was missing a group name or uuid".into()),
556            Self::SC0022Oauth2ClaimMapSyntaxInvalid => Some("A SCIM Oauth2 Claim Map contained invalid syntax".into()),
557            Self::SC0023Oauth2ClaimMapMissingGroupIdentifier => Some("A SCIM Claim Map was missing a group name or uuid".into()),
558            Self::SC0024SshPublicKeySyntaxInvalid => Some("A SCIM Ssh Public Key contained invalid syntax".into()),
559            Self::SC0025UiHintSyntaxInvalid => Some("A SCIM UiHint contained invalid syntax".into()),
560            Self::SC0026Utf8SyntaxInvalid => Some("A SCIM Utf8 String Scope Map contained invalid syntax".into()),
561            Self::SC0027ClassSetInvalid => Some("The internal set of class templates used in this create operation was invalid. THIS IS A BUG.".into()),
562            Self::SC0028CreatedUuidsInvalid => Some("The internal create query did not return the set of created UUIDs. THIS IS A BUG".into()),
563            Self::SC0029PaginationOutOfBounds => Some("The requested range for pagination was out of bounds of the result set".into()),
564
565            Self::UI0001ChallengeSerialisation => Some("The WebAuthn challenge was unable to be serialised.".into()),
566            Self::UI0002InvalidState => Some("The credential update process returned an invalid state transition.".into()),
567            Self::UI0003InvalidOauth2Resume => Some("The server attemped to resume OAuth2, but no OAuth2 session is in progress.".into()),
568            Self::VL0001ValueSshPublicKeyString => None,
569            Self::VS0001IncomingReplSshPublicKey => None,
570            Self::VS0002CertificatePublicKeyDigest |
571            Self::VS0003CertificateDerDecode => Some("Decoding the stored certificate from DER failed.".into()),
572            Self::VS0004CertificatePublicKeyDigest |
573            Self::VS0005CertificatePublicKeyDigest => Some("The certificates public key is unabled to be digested.".into()),
574        }
575    }
576}
577
578#[test]
579fn test_operationerror_as_nice_string() {
580    assert_eq!(
581        OperationError::CU0001WebauthnAttestationNotTrusted.to_string(),
582        "CU0001WebauthnAttestationNotTrusted".to_string()
583    );
584    assert_eq!(
585        OperationError::CU0003WebauthnUserNotVerified.to_string(),
586        "CU0003WebauthnUserNotVerified - User Verification bit not set while registering credential, you may need to configure a PIN on this device.".to_string()
587    );
588    assert_eq!(
589        OperationError::SessionExpired.to_string(),
590        "SessionExpired".to_string()
591    );
592    assert_eq!(
593        OperationError::CorruptedEntry(12345).to_string(),
594        "CorruptedEntry(12345)".to_string()
595    );
596}