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