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    // Migration
225    MG0001InvalidReMigrationLevel,
226    MG0002RaiseDomainLevelExceedsMaximum,
227    MG0003ServerPhaseInvalidForMigration,
228    MG0004DomainLevelInDevelopment,
229    MG0005GidConstraintsNotMet,
230    MG0006SKConstraintsNotMet,
231    MG0007Oauth2StrictConstraintsNotMet,
232    MG0008SkipUpgradeAttempted,
233    MG0009InvalidTargetLevelForBootstrap,
234    //
235    KP0001KeyProviderNotLoaded,
236    KP0002KeyProviderInvalidClass,
237    KP0003KeyProviderInvalidType,
238    KP0004KeyProviderMissingAttributeName,
239    KP0005KeyProviderDuplicate,
240    KP0006KeyObjectJwtEs256Generation,
241    KP0007KeyProviderDefaultNotAvailable,
242    KP0008KeyObjectMissingUuid,
243    KP0009KeyObjectPrivateToDer,
244    KP0010KeyObjectSignerToVerifier,
245    KP0011KeyObjectMissingClass,
246    KP0012KeyObjectMissingProvider,
247    KP0012KeyProviderNotLoaded,
248    KP0013KeyObjectJwsEs256DerInvalid,
249    KP0014KeyObjectSignerToVerifier,
250    KP0015KeyObjectJwsEs256DerInvalid,
251    KP0016KeyObjectJwsEs256DerInvalid,
252    KP0017KeyProviderNoSuchKey,
253    KP0018KeyProviderNoSuchKey,
254    KP0019KeyProviderUnsupportedAlgorithm,
255    KP0020KeyObjectNoActiveSigningKeys,
256    KP0021KeyObjectJwsEs256Signature,
257    KP0022KeyObjectJwsNotAssociated,
258    KP0023KeyObjectJwsKeyRevoked,
259    KP0024KeyObjectJwsInvalid,
260    KP0025KeyProviderNotAvailable,
261    KP0026KeyObjectNoSuchKey,
262    KP0027KeyObjectPublicToDer,
263    KP0028KeyObjectImportJwsEs256DerInvalid,
264    KP0029KeyObjectSignerToVerifier,
265    KP0030KeyObjectPublicToDer,
266    KP0031KeyObjectNotFound,
267    KP0032KeyProviderNoSuchKey,
268    KP0033KeyProviderNoSuchKey,
269    KP0034KeyProviderUnsupportedAlgorithm,
270    KP0035KeyObjectJweA128GCMGeneration,
271    KP0036KeyObjectPrivateToBytes,
272    KP0037KeyObjectImportJweA128GCMInvalid,
273    KP0038KeyObjectImportJweA128GCMInvalid,
274    KP0039KeyObjectJweNotAssociated,
275    KP0040KeyObjectJweInvalid,
276    KP0041KeyObjectJweRevoked,
277    KP0042KeyObjectNoActiveEncryptionKeys,
278    KP0043KeyObjectJweA128GCMEncryption,
279    KP0044KeyObjectJwsPublicJwk,
280
281    KP0045KeyObjectImportJwsRs256DerInvalid,
282    KP0046KeyObjectSignerToVerifier,
283    KP0047KeyObjectPublicToDer,
284    KP0048KeyObjectJwtRs256Generation,
285    KP0049KeyObjectSignerToVerifier,
286    KP0050KeyObjectPrivateToDer,
287    KP0051KeyObjectPublicToDer,
288    KP0052KeyObjectJwsRs256DerInvalid,
289    KP0053KeyObjectSignerToVerifier,
290    KP0054KeyObjectJwsRs256DerInvalid,
291    KP0055KeyObjectJwsRs256DerInvalid,
292    KP0056KeyObjectJwsRs256Signature,
293    KP0057KeyObjectJwsNotAssociated,
294    KP0058KeyObjectJwsInvalid,
295    KP0059KeyObjectJwsKeyRevoked,
296    KP0060KeyObjectJwsPublicJwk,
297    KP0061KeyObjectNoActiveSigningKeys,
298    KP0062KeyProviderNoSuchKey,
299
300    KP0063KeyObjectJwsHs256DerInvalid,
301    KP0064KeyObjectSignerToVerifier,
302    KP0065KeyObjectJwtHs256Generation,
303    KP0066KeyObjectJwsHs256DerInvalid,
304    KP0067KeyObjectSignerToVerifier,
305    KP0068KeyObjectJwsHs256DerInvalid,
306    KP0069KeyObjectNoActiveSigningKeys,
307    KP0070KeyObjectJwsHs256Signature,
308    KP0071KeyObjectPrivateToDer,
309
310    KP0072KeyObjectHs256Invalid,
311    KP0073KeyObjectHs256Invalid,
312    KP0074KeyObjectNoActiveSigningKeys,
313    KP0075KeyObjectHmacInvalidLength,
314    KP0076KeyObjectHkdfOutputLengthInvalid,
315    KP0077KeyProviderNoSuchKey,
316    KP0078KeyObjectNotFound,
317    KP0079KeyObjectNotFound,
318
319    // Plugins
320    PL0001GidOverlapsSystemRange,
321
322    // Web UI
323    UI0001ChallengeSerialisation,
324    UI0002InvalidState,
325    UI0003InvalidOauth2Resume,
326    UI0004MemberAlreadyExists,
327
328    // Unixd Things
329    KU001InitWhileSessionActive,
330    KU002ContinueWhileSessionInActive,
331    KU003PamAuthFailed,
332    KU004PamInitFailed,
333    KU005ErrorCheckingAccount,
334    KU006OnlyRootAllowed,
335}
336
337impl PartialEq for OperationError {
338    fn eq(&self, other: &Self) -> bool {
339        // We do this to avoid InvalidPassword being checked as it's not
340        // derive PartialEq. Generally we only use the PartialEq for TESTING
341        // anyway.
342        std::mem::discriminant(self) == std::mem::discriminant(other)
343    }
344}
345
346impl Display for OperationError {
347    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
348        let mut output = format!("{self:?}")
349            .split("::")
350            .last()
351            .unwrap_or("")
352            .to_string();
353
354        if let Some(msg) = self.message() {
355            output += &format!(" - {msg}");
356        };
357        f.write_str(&output)
358    }
359}
360
361impl OperationError {
362    /// Return the message associated with the error if there is one.
363    pub fn message(&self) -> Option<String> {
364        match self {
365            Self::SessionExpired => None,
366            Self::EmptyRequest => None,
367            Self::Backend => None,
368            Self::NoMatchingEntries => None,
369            Self::NoMatchingAttributes => None,
370            Self::UniqueConstraintViolation => Some("A unique constraint was violated resulting in multiple conflicting results.".into()),
371            Self::CorruptedEntry(_) => None,
372            Self::CorruptedIndex(_) => None,
373            Self::ConsistencyError(_) => None,
374            Self::SchemaViolation(_) => None,
375            Self::Plugin(_) => None,
376            Self::FilterGeneration => None,
377            Self::FilterParseError => None,
378            Self::FilterUuidResolution => None,
379            Self::InvalidAttributeName(_) => None,
380            Self::InvalidAttribute(_) => None,
381            Self::InvalidLabel => Some("The submitted label for this item is invalid.".into()),
382            Self::DuplicateLabel => Some("The submitted label for this item is already in use.".into()),
383            Self::DuplicateKey => Some("The submitted key already exists.".into()),
384            Self::InvalidDbState => None,
385            Self::InvalidCacheState => None,
386            Self::InvalidValueState => None,
387            Self::InvalidEntryId => None,
388            Self::InvalidRequestState => None,
389            Self::InvalidSyncState => None,
390            Self::InvalidState => None,
391            Self::InvalidEntryState => None,
392            Self::InvalidUuid => None,
393            Self::InvalidReplChangeId => None,
394            Self::InvalidAcpState(_) => None,
395            Self::InvalidSchemaState(_) => None,
396            Self::InvalidAccountState(val) => Some(format!("Invalid account state: {val}")),
397            Self::MissingClass(val) => Some(format!("Missing class: {val}")),
398            Self::MissingAttribute(val) => Some(format!("Missing attribute: {val}")),
399            Self::AttributeUniqueness(attrs) => Some(format!("The value of some attributes is not unique. {attrs:?}")),
400            Self::MissingEntries => None,
401            Self::ModifyAssertionFailed => None,
402            Self::BackendEngine => None,
403            Self::SqliteError => None,
404            Self::FsError => None,
405            Self::SerdeJsonError => None,
406            Self::SerdeCborError => None,
407            Self::AccessDenied => None,
408            Self::NotAuthenticated => None,
409            Self::NotAuthorised => None,
410            Self::InvalidAuthState(_) => None,
411            Self::InvalidSessionState => None,
412            Self::SystemProtectedObject => None,
413            Self::SystemProtectedAttribute => None,
414            Self::PasswordQuality(_) => None,
415            Self::CryptographyError => None,
416            Self::ResourceLimit => None,
417            Self::QueueDisconnected => None,
418            Self::Webauthn => None,
419            Self::Wait(_) => None,
420            Self::CannotStartMFADuringOngoingMFASession => Some("Cannot start a new MFA authentication flow when there already is one active.".into()),
421            Self::ReplReplayFailure => None,
422            Self::ReplEntryNotChanged => None,
423            Self::ReplInvalidRUVState => None,
424            Self::ReplDomainLevelUnsatisfiable => None,
425            Self::ReplDomainUuidMismatch => None,
426            Self::ReplServerUuidSplitDataState => None,
427            Self::TransactionAlreadyCommitted => None,
428            Self::ValueDenyName => None,
429            Self::DatabaseLockAcquisitionTimeout => Some("Unable to acquire a database lock - the current server may be too busy. Try again later.".into()),
430            Self::ReferenceLoop => Some("The change you have made would introduce an invalid reference loop. Unable to proceed.".into()),
431
432    Self::AU0001InvalidState => Some("Invalid authentication session state for request".into()),
433    Self::AU0002JwsSerialisation => Some("JWS serialisation failed".into()),
434    Self::AU0003JwsSignature => Some("JWS signature failed".into()),
435    Self::AU0004UserAuthTokenInvalid => Some("User auth token was unable to be generated".into()),
436    Self::AU0005DelayedProcessFailure => Some("Delaying processing failure, unable to proceed".into()),
437    Self::AU0006CredentialMayNotReauthenticate => Some("Credential may not reauthenticate".into()),
438    Self::AU0007UserAuthTokenInvalid => Some("User auth token was unable to be generated".into()),
439    Self::AU0008ClientAuthInfoPrevalidation => Some("Client Authentication Info prevalidation did not occur when expected".into()),
440
441            Self::CU0001WebauthnAttestationNotTrusted => None,
442            Self::CU0002WebauthnRegistrationError => None,
443            Self::CU0003WebauthnUserNotVerified => Some("User Verification bit not set while registering credential, you may need to configure a PIN on this device.".into()),
444
445            Self::CU0004SessionInconsistent => Some("The session is unable to be committed due to unresolved warnings.".into()),
446            Self::CU0005IntentTokenConflict => Some("The intent token used to create this session has been reused in another browser/tab and may not proceed.".into()),
447            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()),
448
449            Self::DB0001MismatchedRestoreVersion => None,
450            Self::DB0002MismatchedRestoreVersion => None,
451            Self::DB0003FilterResolveCacheBuild => None,
452            Self::DB0004DatabaseTooOld => Some("The database is too old to be migrated.".into()),
453            Self::KG001TaskTimeout => Some("Task timed out".into()),
454            Self::KG002TaskCommFailure => Some("Inter-Task communication failure".into()),
455            Self::KG003CacheClearFailed => Some("Failed to clear cache".into()),
456            Self::KG004UnknownFeatureUuid => None,
457            Self::KG005HowDidYouEvenManageThis => Some("You have damaged the fabric of space time and managed to perform an impossible action.".into()),
458            Self::KG006DatastructureCorruption => None,
459            Self::KP0001KeyProviderNotLoaded => None,
460            Self::KP0002KeyProviderInvalidClass => None,
461            Self::KP0003KeyProviderInvalidType => None,
462            Self::KP0004KeyProviderMissingAttributeName => None,
463            Self::KP0005KeyProviderDuplicate => None,
464            Self::KP0006KeyObjectJwtEs256Generation => None,
465            Self::KP0007KeyProviderDefaultNotAvailable => None,
466            Self::KP0008KeyObjectMissingUuid => None,
467            Self::KP0009KeyObjectPrivateToDer => None,
468            Self::KP0010KeyObjectSignerToVerifier => None,
469            Self::KP0011KeyObjectMissingClass => None,
470            Self::KP0012KeyObjectMissingProvider => None,
471            Self::KP0012KeyProviderNotLoaded => None,
472            Self::KP0013KeyObjectJwsEs256DerInvalid => None,
473            Self::KP0014KeyObjectSignerToVerifier => None,
474            Self::KP0015KeyObjectJwsEs256DerInvalid => None,
475            Self::KP0016KeyObjectJwsEs256DerInvalid => None,
476            Self::KP0017KeyProviderNoSuchKey => None,
477            Self::KP0018KeyProviderNoSuchKey => None,
478            Self::KP0019KeyProviderUnsupportedAlgorithm => None,
479            Self::KP0020KeyObjectNoActiveSigningKeys => None,
480            Self::KP0021KeyObjectJwsEs256Signature => None,
481            Self::KP0022KeyObjectJwsNotAssociated => None,
482            Self::KP0023KeyObjectJwsKeyRevoked => None,
483            Self::KP0024KeyObjectJwsInvalid => None,
484            Self::KP0025KeyProviderNotAvailable => None,
485            Self::KP0026KeyObjectNoSuchKey => None,
486            Self::KP0027KeyObjectPublicToDer => None,
487            Self::KP0028KeyObjectImportJwsEs256DerInvalid => None,
488            Self::KP0029KeyObjectSignerToVerifier => None,
489            Self::KP0030KeyObjectPublicToDer => None,
490            Self::KP0031KeyObjectNotFound => None,
491            Self::KP0032KeyProviderNoSuchKey => None,
492            Self::KP0033KeyProviderNoSuchKey => None,
493            Self::KP0034KeyProviderUnsupportedAlgorithm => None,
494            Self::KP0035KeyObjectJweA128GCMGeneration => None,
495            Self::KP0036KeyObjectPrivateToBytes => None,
496            Self::KP0037KeyObjectImportJweA128GCMInvalid => None,
497            Self::KP0038KeyObjectImportJweA128GCMInvalid => None,
498            Self::KP0039KeyObjectJweNotAssociated => None,
499            Self::KP0040KeyObjectJweInvalid => None,
500            Self::KP0041KeyObjectJweRevoked => None,
501            Self::KP0042KeyObjectNoActiveEncryptionKeys => None,
502            Self::KP0043KeyObjectJweA128GCMEncryption => None,
503            Self::KP0044KeyObjectJwsPublicJwk => None,
504
505            Self::KP0045KeyObjectImportJwsRs256DerInvalid => None,
506            Self::KP0046KeyObjectSignerToVerifier => None,
507            Self::KP0047KeyObjectPublicToDer => None,
508            Self::KP0048KeyObjectJwtRs256Generation => None,
509            Self::KP0049KeyObjectSignerToVerifier => None,
510            Self::KP0050KeyObjectPrivateToDer => None,
511            Self::KP0051KeyObjectPublicToDer => None,
512            Self::KP0052KeyObjectJwsRs256DerInvalid => None,
513            Self::KP0053KeyObjectSignerToVerifier => None,
514            Self::KP0054KeyObjectJwsRs256DerInvalid => None,
515            Self::KP0055KeyObjectJwsRs256DerInvalid => None,
516            Self::KP0056KeyObjectJwsRs256Signature => None,
517            Self::KP0057KeyObjectJwsNotAssociated => None,
518            Self::KP0058KeyObjectJwsInvalid => None,
519            Self::KP0059KeyObjectJwsKeyRevoked => None,
520            Self::KP0060KeyObjectJwsPublicJwk => None,
521            Self::KP0061KeyObjectNoActiveSigningKeys => None,
522            Self::KP0062KeyProviderNoSuchKey => None,
523            Self::KP0063KeyObjectJwsHs256DerInvalid => None,
524            Self::KP0064KeyObjectSignerToVerifier => None,
525            Self::KP0065KeyObjectJwtHs256Generation => None,
526            Self::KP0066KeyObjectJwsHs256DerInvalid => None,
527            Self::KP0067KeyObjectSignerToVerifier => None,
528            Self::KP0068KeyObjectJwsHs256DerInvalid => None,
529            Self::KP0069KeyObjectNoActiveSigningKeys => None,
530            Self::KP0070KeyObjectJwsHs256Signature => None,
531            Self::KP0071KeyObjectPrivateToDer => None,
532            Self::KP0072KeyObjectHs256Invalid => None,
533            Self::KP0073KeyObjectHs256Invalid => None,
534            Self::KP0074KeyObjectNoActiveSigningKeys => None,
535            Self::KP0075KeyObjectHmacInvalidLength => None,
536            Self::KP0076KeyObjectHkdfOutputLengthInvalid => None,
537            Self::KP0077KeyProviderNoSuchKey => None,
538            Self::KP0078KeyObjectNotFound => None,
539            Self::KP0079KeyObjectNotFound => None,
540
541            Self::KU001InitWhileSessionActive => Some("The session was active when the init function was called.".into()),
542            Self::KU002ContinueWhileSessionInActive => Some("Attempted to continue auth session while current session is inactive".into()),
543            Self::KU003PamAuthFailed => Some("Failed PAM account authentication step".into()),
544            Self::KU004PamInitFailed => Some("Failed to initialise PAM authentication".into()),
545            Self::KU005ErrorCheckingAccount => Some("Error checking account".into()),
546            Self::KU006OnlyRootAllowed => Some("Only root is allowed to perform this operation".into()),
547            Self::LD0001AnonymousNotAllowed => Some("Anonymous is not allowed to access LDAP with this method.".into()),
548            Self::MG0001InvalidReMigrationLevel => None,
549            Self::MG0002RaiseDomainLevelExceedsMaximum => None,
550            Self::MG0003ServerPhaseInvalidForMigration => None,
551            Self::MG0004DomainLevelInDevelopment => None,
552            Self::MG0005GidConstraintsNotMet => None,
553            Self::MG0006SKConstraintsNotMet => Some("Migration Constraints Not Met - Security Keys should not be present.".into()),
554            Self::MG0007Oauth2StrictConstraintsNotMet => Some("Migration Constraints Not Met - All OAuth2 clients must have strict-redirect-uri mode enabled.".into()),
555            Self::MG0008SkipUpgradeAttempted => Some("Skip Upgrade Attempted.".into()),
556            Self::MG0009InvalidTargetLevelForBootstrap => Some("The request target domain level was not valid for bootstrapping a new server instance".into()),
557            Self::PL0001GidOverlapsSystemRange => None,
558            Self::SC0001IncomingSshPublicKey => None,
559            Self::SC0002ReferenceSyntaxInvalid => Some("A SCIM Reference Set contained invalid syntax and can not be processed.".into()),
560            Self::SC0003MailSyntaxInvalid => Some("A SCIM Mail Address contained invalid syntax".into()),
561            Self::SC0004UuidSyntaxInvalid => Some("A SCIM Uuid contained invalid syntax".into()),
562            Self::SC0005BoolSyntaxInvalid => Some("A SCIM boolean contained invalid syntax".into()),
563            Self::SC0006Uint32SyntaxInvalid => Some("A SCIM Uint32 contained invalid syntax".into()),
564            Self::SC0007UrlSyntaxInvalid => Some("A SCIM Url contained invalid syntax".into()),
565            Self::SC0008SyntaxTypeSyntaxInvalid => Some("A SCIM SyntaxType contained invalid syntax".into()),
566            Self::SC0009IndexTypeSyntaxInvalid => Some("A SCIM IndexType contained invalid syntax".into()),
567            Self::SC0010DateTimeSyntaxInvalid => Some("A SCIM DateTime contained invalid syntax".into()),
568
569            Self::SC0011AddressSyntaxInvalid => Some("A SCIM Address contained invalid syntax".into()),
570            Self::SC0012CertificateSyntaxInvalid => Some("A SCIM Certificate contained invalid binary data".into()),
571            Self::SC0013CertificateInvalidDer => Some("A SCIM Certificate did not contain valid DER".into()),
572            Self::SC0014CertificateInvalidDigest => Some("A SCIM Certificate was unable to be digested".into()),
573            Self::SC0015CredentialTypeSyntaxInvalid => Some("A SCIM CredentialType contained invalid syntax".into()),
574            Self::SC0016InameSyntaxInvalid => Some("A SCIM Iname string contained invalid syntax".into()),
575            Self::SC0017Iutf8SyntaxInvalid => Some("A SCIM Iutf8 string contained invalid syntax".into()),
576            Self::SC0018NsUniqueIdSyntaxInvalid => Some("A SCIM NsUniqueID contained invalid syntax".into()),
577            Self::SC0019Oauth2ScopeSyntaxInvalid => Some("A SCIM Oauth2 Scope contained invalid syntax".into()),
578            Self::SC0020Oauth2ScopeMapSyntaxInvalid => Some("A SCIM Oauth2 Scope Map contained invalid syntax".into()),
579            Self::SC0021Oauth2ScopeMapMissingGroupIdentifier => Some("A SCIM Oauth2 Scope Map was missing a group name or uuid".into()),
580            Self::SC0022Oauth2ClaimMapSyntaxInvalid => Some("A SCIM Oauth2 Claim Map contained invalid syntax".into()),
581            Self::SC0023Oauth2ClaimMapMissingGroupIdentifier => Some("A SCIM Claim Map was missing a group name or uuid".into()),
582            Self::SC0024SshPublicKeySyntaxInvalid => Some("A SCIM Ssh Public Key contained invalid syntax".into()),
583            Self::SC0025UiHintSyntaxInvalid => Some("A SCIM UiHint contained invalid syntax".into()),
584            Self::SC0026Utf8SyntaxInvalid => Some("A SCIM Utf8 String Scope Map contained invalid syntax".into()),
585            Self::SC0027ClassSetInvalid => Some("The internal set of class templates used in this create operation was invalid. THIS IS A BUG.".into()),
586            Self::SC0028CreatedUuidsInvalid => Some("The internal create query did not return the set of created UUIDs. THIS IS A BUG".into()),
587            Self::SC0029PaginationOutOfBounds => Some("The requested range for pagination was out of bounds of the result set".into()),
588            Self::SC0030Sha256SyntaxInvalid => Some("A SCIM SHA256 hex string was invalid.".into()),
589
590            Self::UI0001ChallengeSerialisation => Some("The WebAuthn challenge was unable to be serialised.".into()),
591            Self::UI0002InvalidState => Some("The credential update process returned an invalid state transition.".into()),
592            Self::UI0003InvalidOauth2Resume => Some("The server attempted to resume OAuth2, but no OAuth2 session is in progress.".into()),
593            Self::UI0004MemberAlreadyExists => Some("The target is already a member.".into()),
594            Self::VL0001ValueSshPublicKeyString => None,
595            Self::VS0001IncomingReplSshPublicKey => None,
596            Self::VS0002CertificatePublicKeyDigest |
597            Self::VS0003CertificateDerDecode => Some("Decoding the stored certificate from DER failed.".into()),
598            Self::VS0004CertificatePublicKeyDigest |
599            Self::VS0005CertificatePublicKeyDigest => Some("The certificates public key is unable to be digested.".into()),
600
601        }
602    }
603}
604
605#[test]
606fn test_operationerror_as_nice_string() {
607    assert_eq!(
608        OperationError::CU0001WebauthnAttestationNotTrusted.to_string(),
609        "CU0001WebauthnAttestationNotTrusted".to_string()
610    );
611    assert_eq!(
612        OperationError::CU0003WebauthnUserNotVerified.to_string(),
613        "CU0003WebauthnUserNotVerified - User Verification bit not set while registering credential, you may need to configure a PIN on this device.".to_string()
614    );
615    assert_eq!(
616        OperationError::SessionExpired.to_string(),
617        "SessionExpired".to_string()
618    );
619    assert_eq!(
620        OperationError::CorruptedEntry(12345).to_string(),
621        "CorruptedEntry(12345)".to_string()
622    );
623}