kanidm_proto/internal/
error.rs

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