Skip to main content

kanidm_proto/
attribute.rs

1use crate::constants::*;
2use crate::internal::OperationError;
3use serde::{Deserialize, Serialize};
4use std::convert::Infallible;
5use std::fmt;
6use std::str::FromStr;
7use utoipa::ToSchema;
8
9pub use smartstring::alias::String as AttrString;
10
11#[derive(
12    Serialize, Deserialize, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash, Default, ToSchema,
13)]
14#[cfg_attr(test, derive(enum_iterator::Sequence))]
15#[serde(rename_all = "lowercase", from = "String", into = "AttrString")]
16pub enum Attribute {
17    Account,
18    AccountExpire,
19    AccountValidFrom,
20    AccountSoftlockExpire,
21    AcpCreateAttr,
22    AcpCreateClass,
23    AcpEnable,
24    AcpModifyClass,
25    AcpModifyPresentClass,
26    AcpModifyRemoveClass,
27    AcpModifyPresentAttr,
28    AcpModifyRemovedAttr,
29    AcpReceiver,
30    AcpReceiverGroup,
31    AcpSearchAttr,
32    AcpTargetScope,
33    ApiTokenSession,
34    ApplicationPassword,
35    ApplicationUrl,
36    AttestedPasskeys,
37    #[default]
38    Attr,
39    AttributeName,
40    AttributeType,
41    AuthSessionExpiry,
42    AuthPasswordMinimumLength,
43    BadlistPassword,
44    Certificate,
45    CascadeDeleted,
46    Claim,
47    Class,
48    ClassName,
49    Cn,
50    CookiePrivateKey,
51    CreatedAtCid,
52    CredentialUpdateIntentToken,
53    CredentialTypeMinimum,
54    DeniedName,
55    DeleteAfter,
56    Description,
57    DirectMemberOf,
58    DisplayName,
59    Dn,
60    Domain,
61    DomainAllowEasterEggs,
62    DomainAllowAccountRecovery,
63    DomainDevelopmentTaint,
64    DomainDisplayName,
65    DomainLdapBasedn,
66    DomainName,
67    DomainSsid,
68    DomainTokenKey,
69    DomainUuid,
70    DynGroup,
71    DynGroupFilter,
72    DynMember,
73    Enabled,
74    Email,
75    EmailAlternative,
76    EmailPrimary,
77    EntryDn,
78    EntryManagedBy,
79    EntryUuid,
80    Es256PrivateKeyDer,
81    Excludes,
82    FernetPrivateKeyStr,
83    Gecos,
84    GidNumber,
85    GrantUiHint,
86    Group,
87    HmacNameHistory,
88    HomeDirectory,
89    IdVerificationEcKey,
90    Image,
91    Index,
92    Indexed,
93    InMemoriam,
94    IpaNtHash,
95    IpaSshPubKey,
96    JwsEs256PrivateKey,
97    KeyActionRotate,
98    KeyActionRevoke,
99    KeyActionImportJwsEs256,
100    KeyActionImportJwsRs256,
101    KeyInternalData,
102    KeyProvider,
103    LastModifiedCid,
104    LdapAllowUnixPwBind,
105    /// An LDAP Compatible emailAddress
106    LdapEmailAddress,
107    /// An LDAP Compatible sshkeys virtual attribute
108    LdapKeys,
109    LdapMaxQueryableAttrs,
110    LegalName,
111    LimitSearchMaxResults,
112    LimitSearchMaxFilterTest,
113    LinkedGroup,
114    LoginShell,
115    Mail,
116    MailDestination,
117    May,
118    Member,
119    MemberCreateOnce,
120    MemberOf,
121    MessageTemplate,
122    MultiValue,
123    Must,
124    Name,
125    NameHistory,
126    NoIndex,
127    NsUniqueId,
128    NsAccountLock,
129    OAuth2AllowInsecureClientDisablePkce,
130    OAuth2AllowLocalhostRedirect,
131    OAuth2AuthorisationEndpoint,
132    OAuth2ClientId,
133    OAuth2ClientSecret,
134    OAuth2ConsentScopeMap,
135    OAuth2DeviceFlowEnable,
136    OAuth2JwtLegacyCryptoEnable,
137    OAuth2PreferShortUsername,
138    OAuth2RefreshTokenExpiry,
139    OAuth2RequestScopes,
140    OAuth2RsBasicSecret,
141    OAuth2RsClaimMap,
142    OAuth2RsImplicitScopes,
143    OAuth2RsName,
144    OAuth2RsOrigin,
145    OAuth2RsOriginLanding,
146    OAuth2RsScopeMap,
147    OAuth2RsSupScopeMap,
148    OAuth2RsTokenKey,
149    OAuth2Session,
150    OAuth2StrictRedirectUri,
151    OAuth2TokenEndpoint,
152    OAuth2AccountCredentialUuid,
153    OAuth2AccountProvider,
154    OAuth2AccountUniqueUserId,
155    OAuth2ConsentPromptEnable,
156    ObjectClass,
157    OtherNoIndex,
158    PassKeys,
159    PasswordImport,
160    PasswordChangedTime,
161    PatchLevel,
162    Phantom,
163    PrimaryCredential,
164    PrivateCookieKey,
165    PrivilegeExpiry,
166    RadiusSecret,
167    RecycledDirectMemberOf,
168    Refers,
169    Replicated,
170    Rs256PrivateKeyDer,
171    S256,
172    /// A set of scim schemas. This is similar to a kanidm class.
173    #[serde(rename = "schemas")]
174    ScimSchemas,
175    Scope,
176    SendAfter,
177    SentAt,
178    SourceUuid,
179    Spn,
180    /// An LDAP-compatible sshpublickey
181    LdapSshPublicKey,
182    /// The Kanidm-local ssh_publickey
183    SshPublicKey,
184    SudoHost,
185    Supplements,
186    SystemSupplements,
187    SyncAllowed,
188    SyncClass,
189    SyncCookie,
190    SyncCredentialPortal,
191    SyncExternalId,
192    SyncParentUuid,
193    SyncTokenSession,
194    SyncYieldAuthority,
195    Syntax,
196    SystemExcludes,
197    SystemMay,
198    SystemMust,
199    Term,
200    TotpImport,
201    Uid,
202    UidNumber,
203    Unique,
204    UnixPassword,
205    UnixPasswordImport,
206    UserAuthTokenSession,
207    UserId,
208    UserPassword,
209    Uuid,
210    Version,
211    WebauthnAttestationCaList,
212    AllowPrimaryCredFallback,
213
214    #[cfg(any(debug_assertions, test, feature = "test"))]
215    NonExist,
216    #[cfg(any(debug_assertions, test, feature = "test"))]
217    TestAttr,
218    #[cfg(test)]
219    TestAttrA,
220    #[cfg(test)]
221    TestAttrB,
222    #[cfg(test)]
223    TestAttrC,
224    #[cfg(test)]
225    TestAttrD,
226    #[cfg(any(debug_assertions, test, feature = "test"))]
227    TestNumber,
228    #[cfg(any(debug_assertions, test, feature = "test"))]
229    Extra,
230    #[cfg(any(debug_assertions, test, feature = "test"))]
231    TestNotAllowed,
232
233    #[cfg(not(test))]
234    #[schema(value_type = String)]
235    Custom(AttrString),
236}
237
238impl AsRef<str> for Attribute {
239    fn as_ref(&self) -> &str {
240        self.as_str()
241    }
242}
243
244impl AsRef<Attribute> for Attribute {
245    fn as_ref(&self) -> &Attribute {
246        self
247    }
248}
249
250impl TryFrom<&AttrString> for Attribute {
251    type Error = OperationError;
252
253    fn try_from(value: &AttrString) -> Result<Self, Self::Error> {
254        Ok(Attribute::inner_from_str(value.as_str()))
255    }
256}
257
258impl From<&str> for Attribute {
259    fn from(value: &str) -> Self {
260        Self::inner_from_str(value)
261    }
262}
263
264impl From<String> for Attribute {
265    fn from(value: String) -> Self {
266        Self::inner_from_str(value.as_str())
267    }
268}
269
270impl<'a> From<&'a Attribute> for &'a str {
271    fn from(val: &'a Attribute) -> Self {
272        val.as_str()
273    }
274}
275
276impl From<Attribute> for AttrString {
277    fn from(val: Attribute) -> Self {
278        AttrString::from(val.as_str())
279    }
280}
281
282impl FromStr for Attribute {
283    type Err = Infallible;
284
285    fn from_str(value: &str) -> Result<Self, Self::Err> {
286        Ok(Self::inner_from_str(value))
287    }
288}
289
290impl Attribute {
291    pub fn as_str(&self) -> &str {
292        match self {
293            Attribute::Account => ATTR_ACCOUNT,
294            Attribute::AccountExpire => ATTR_ACCOUNT_EXPIRE,
295            Attribute::AccountValidFrom => ATTR_ACCOUNT_VALID_FROM,
296            Attribute::AccountSoftlockExpire => ATTR_ACCOUNT_SOFTLOCK_EXPIRE,
297            Attribute::AcpCreateAttr => ATTR_ACP_CREATE_ATTR,
298            Attribute::AcpCreateClass => ATTR_ACP_CREATE_CLASS,
299            Attribute::AcpEnable => ATTR_ACP_ENABLE,
300            Attribute::AcpModifyClass => ATTR_ACP_MODIFY_CLASS,
301            Attribute::AcpModifyPresentClass => ATTR_ACP_MODIFY_PRESENT_CLASS,
302            Attribute::AcpModifyRemoveClass => ATTR_ACP_MODIFY_REMOVE_CLASS,
303            Attribute::AcpModifyPresentAttr => ATTR_ACP_MODIFY_PRESENTATTR,
304            Attribute::AcpModifyRemovedAttr => ATTR_ACP_MODIFY_REMOVEDATTR,
305            Attribute::AcpReceiver => ATTR_ACP_RECEIVER,
306            Attribute::AcpReceiverGroup => ATTR_ACP_RECEIVER_GROUP,
307            Attribute::AcpSearchAttr => ATTR_ACP_SEARCH_ATTR,
308            Attribute::AcpTargetScope => ATTR_ACP_TARGET_SCOPE,
309            Attribute::AllowPrimaryCredFallback => ATTR_ALLOW_PRIMARY_CRED_FALLBACK,
310            Attribute::ApiTokenSession => ATTR_API_TOKEN_SESSION,
311            Attribute::ApplicationPassword => ATTR_APPLICATION_PASSWORD,
312            Attribute::ApplicationUrl => ATTR_APPLICATION_URL,
313            Attribute::AttestedPasskeys => ATTR_ATTESTED_PASSKEYS,
314            Attribute::Attr => ATTR_ATTR,
315            Attribute::AttributeName => ATTR_ATTRIBUTENAME,
316            Attribute::AttributeType => ATTR_ATTRIBUTETYPE,
317            Attribute::AuthSessionExpiry => ATTR_AUTH_SESSION_EXPIRY,
318            Attribute::AuthPasswordMinimumLength => ATTR_AUTH_PASSWORD_MINIMUM_LENGTH,
319            Attribute::BadlistPassword => ATTR_BADLIST_PASSWORD,
320            Attribute::Certificate => ATTR_CERTIFICATE,
321            Attribute::CascadeDeleted => ATTR_CASCADE_DELETED,
322            Attribute::Claim => ATTR_CLAIM,
323            Attribute::Class => ATTR_CLASS,
324            Attribute::ClassName => ATTR_CLASSNAME,
325            Attribute::Cn => ATTR_CN,
326            Attribute::CookiePrivateKey => ATTR_COOKIE_PRIVATE_KEY,
327            Attribute::CreatedAtCid => ATTR_CREATED_AT_CID,
328            Attribute::CredentialUpdateIntentToken => ATTR_CREDENTIAL_UPDATE_INTENT_TOKEN,
329            Attribute::CredentialTypeMinimum => ATTR_CREDENTIAL_TYPE_MINIMUM,
330            Attribute::DeniedName => ATTR_DENIED_NAME,
331            Attribute::DeleteAfter => ATTR_DELETE_AFTER,
332            Attribute::Description => ATTR_DESCRIPTION,
333            Attribute::DirectMemberOf => ATTR_DIRECTMEMBEROF,
334            Attribute::DisplayName => ATTR_DISPLAYNAME,
335            Attribute::Dn => ATTR_DN,
336            Attribute::Domain => ATTR_DOMAIN,
337            Attribute::DomainAllowEasterEggs => ATTR_DOMAIN_ALLOW_EASTER_EGGS,
338            Attribute::DomainAllowAccountRecovery => ATTR_DOMAIN_ALLOW_ACCOUNT_RECOVERY,
339            Attribute::DomainDevelopmentTaint => ATTR_DOMAIN_DEVELOPMENT_TAINT,
340            Attribute::DomainDisplayName => ATTR_DOMAIN_DISPLAY_NAME,
341            Attribute::DomainLdapBasedn => ATTR_DOMAIN_LDAP_BASEDN,
342            Attribute::DomainName => ATTR_DOMAIN_NAME,
343            Attribute::DomainSsid => ATTR_DOMAIN_SSID,
344            Attribute::DomainTokenKey => ATTR_DOMAIN_TOKEN_KEY,
345            Attribute::DomainUuid => ATTR_DOMAIN_UUID,
346            Attribute::DynGroup => ATTR_DYNGROUP,
347            Attribute::DynGroupFilter => ATTR_DYNGROUP_FILTER,
348            Attribute::DynMember => ATTR_DYNMEMBER,
349            Attribute::Enabled => ATTR_ENABLED,
350            Attribute::Email => ATTR_EMAIL,
351            Attribute::EmailAlternative => ATTR_EMAIL_ALTERNATIVE,
352            Attribute::EmailPrimary => ATTR_EMAIL_PRIMARY,
353            Attribute::EntryDn => ATTR_ENTRYDN,
354            Attribute::EntryManagedBy => ATTR_ENTRY_MANAGED_BY,
355            Attribute::EntryUuid => ATTR_ENTRYUUID,
356            Attribute::Es256PrivateKeyDer => ATTR_ES256_PRIVATE_KEY_DER,
357            Attribute::Excludes => ATTR_EXCLUDES,
358            Attribute::FernetPrivateKeyStr => ATTR_FERNET_PRIVATE_KEY_STR,
359            Attribute::Gecos => ATTR_GECOS,
360            Attribute::GidNumber => ATTR_GIDNUMBER,
361            Attribute::GrantUiHint => ATTR_GRANT_UI_HINT,
362            Attribute::Group => ATTR_GROUP,
363            Attribute::HmacNameHistory => ATTR_HMAC_NAME_HISTORY,
364            Attribute::HomeDirectory => ATTR_HOME_DIRECTORY,
365            Attribute::IdVerificationEcKey => ATTR_ID_VERIFICATION_ECKEY,
366            Attribute::Image => ATTR_IMAGE,
367            Attribute::Index => ATTR_INDEX,
368            Attribute::Indexed => ATTR_INDEXED,
369            Attribute::InMemoriam => ATTR_IN_MEMORIAM,
370            Attribute::IpaNtHash => ATTR_IPANTHASH,
371            Attribute::IpaSshPubKey => ATTR_IPASSHPUBKEY,
372            Attribute::JwsEs256PrivateKey => ATTR_JWS_ES256_PRIVATE_KEY,
373            Attribute::KeyActionRotate => ATTR_KEY_ACTION_ROTATE,
374            Attribute::KeyActionRevoke => ATTR_KEY_ACTION_REVOKE,
375            Attribute::KeyActionImportJwsEs256 => ATTR_KEY_ACTION_IMPORT_JWS_ES256,
376            Attribute::KeyActionImportJwsRs256 => ATTR_KEY_ACTION_IMPORT_JWS_RS256,
377            Attribute::KeyInternalData => ATTR_KEY_INTERNAL_DATA,
378            Attribute::KeyProvider => ATTR_KEY_PROVIDER,
379            Attribute::LastModifiedCid => ATTR_LAST_MODIFIED_CID,
380            Attribute::LdapAllowUnixPwBind => ATTR_LDAP_ALLOW_UNIX_PW_BIND,
381            Attribute::LdapEmailAddress => ATTR_LDAP_EMAIL_ADDRESS,
382            Attribute::LdapKeys => ATTR_LDAP_KEYS,
383            Attribute::LdapMaxQueryableAttrs => ATTR_LDAP_MAX_QUERYABLE_ATTRS,
384            Attribute::LdapSshPublicKey => ATTR_LDAP_SSHPUBLICKEY,
385            Attribute::LegalName => ATTR_LEGALNAME,
386            Attribute::LimitSearchMaxResults => ATTR_LIMIT_SEARCH_MAX_RESULTS,
387            Attribute::LimitSearchMaxFilterTest => ATTR_LIMIT_SEARCH_MAX_FILTER_TEST,
388            Attribute::LinkedGroup => ATTR_LINKEDGROUP,
389            Attribute::LoginShell => ATTR_LOGINSHELL,
390            Attribute::Mail => ATTR_MAIL,
391            Attribute::MailDestination => ATTR_MAIL_DESTINATION,
392            Attribute::May => ATTR_MAY,
393            Attribute::Member => ATTR_MEMBER,
394            Attribute::MemberCreateOnce => ATTR_MEMBER_CREATE_ONCE,
395            Attribute::MemberOf => ATTR_MEMBEROF,
396            Attribute::MessageTemplate => ATTR_MESSAGE_TEMPLATE,
397            Attribute::MultiValue => ATTR_MULTIVALUE,
398            Attribute::Must => ATTR_MUST,
399            Attribute::Name => ATTR_NAME,
400            Attribute::NameHistory => ATTR_NAME_HISTORY,
401            Attribute::NoIndex => ATTR_NO_INDEX,
402            Attribute::NsUniqueId => ATTR_NSUNIQUEID,
403            Attribute::NsAccountLock => ATTR_NSACCOUNTLOCK,
404            Attribute::OAuth2AllowInsecureClientDisablePkce => {
405                ATTR_OAUTH2_ALLOW_INSECURE_CLIENT_DISABLE_PKCE
406            }
407            Attribute::OAuth2AllowLocalhostRedirect => ATTR_OAUTH2_ALLOW_LOCALHOST_REDIRECT,
408            Attribute::OAuth2AuthorisationEndpoint => ATTR_OAUTH2_AUTHORISATION_ENDPOINT,
409            Attribute::OAuth2ClientId => ATTR_OAUTH2_CLIENT_ID,
410            Attribute::OAuth2ClientSecret => ATTR_OAUTH2_CLIENT_SECRET,
411            Attribute::OAuth2ConsentScopeMap => ATTR_OAUTH2_CONSENT_SCOPE_MAP,
412            Attribute::OAuth2DeviceFlowEnable => ATTR_OAUTH2_DEVICE_FLOW_ENABLE,
413            Attribute::OAuth2JwtLegacyCryptoEnable => ATTR_OAUTH2_JWT_LEGACY_CRYPTO_ENABLE,
414            Attribute::OAuth2PreferShortUsername => ATTR_OAUTH2_PREFER_SHORT_USERNAME,
415            Attribute::OAuth2RefreshTokenExpiry => ATTR_OAUTH2_REFRESH_TOKEN_EXPIRY,
416            Attribute::OAuth2RequestScopes => ATTR_OAUTH2_REQUEST_SCOPES,
417            Attribute::OAuth2RsBasicSecret => ATTR_OAUTH2_RS_BASIC_SECRET,
418            Attribute::OAuth2RsClaimMap => ATTR_OAUTH2_RS_CLAIM_MAP,
419            Attribute::OAuth2RsImplicitScopes => ATTR_OAUTH2_RS_IMPLICIT_SCOPES,
420            Attribute::OAuth2RsName => ATTR_OAUTH2_RS_NAME,
421            Attribute::OAuth2RsOrigin => ATTR_OAUTH2_RS_ORIGIN,
422            Attribute::OAuth2RsOriginLanding => ATTR_OAUTH2_RS_ORIGIN_LANDING,
423            Attribute::OAuth2RsScopeMap => ATTR_OAUTH2_RS_SCOPE_MAP,
424            Attribute::OAuth2RsSupScopeMap => ATTR_OAUTH2_RS_SUP_SCOPE_MAP,
425            Attribute::OAuth2RsTokenKey => ATTR_OAUTH2_RS_TOKEN_KEY,
426            Attribute::OAuth2Session => ATTR_OAUTH2_SESSION,
427            Attribute::OAuth2StrictRedirectUri => ATTR_OAUTH2_STRICT_REDIRECT_URI,
428            Attribute::OAuth2TokenEndpoint => ATTR_OAUTH2_TOKEN_ENDPOINT,
429            Attribute::OAuth2AccountCredentialUuid => ATTR_OAUTH2_ACCOUNT_CREDENTIAL_UUID,
430            Attribute::OAuth2AccountProvider => ATTR_OAUTH2_ACCOUNT_PROVIDER,
431            Attribute::OAuth2AccountUniqueUserId => ATTR_OAUTH2_ACCOUNT_UNIQUE_USER_ID,
432            Attribute::OAuth2ConsentPromptEnable => ATTR_OAUTH2_CONSENT_PROMPT_ENABLE,
433            Attribute::ObjectClass => ATTR_OBJECTCLASS,
434            Attribute::OtherNoIndex => ATTR_OTHER_NO_INDEX,
435            Attribute::PassKeys => ATTR_PASSKEYS,
436            Attribute::PasswordChangedTime => ATTR_PWD_CHANGED_TIME,
437            Attribute::PasswordImport => ATTR_PASSWORD_IMPORT,
438            Attribute::PatchLevel => ATTR_PATCH_LEVEL,
439            Attribute::Phantom => ATTR_PHANTOM,
440            Attribute::PrimaryCredential => ATTR_PRIMARY_CREDENTIAL,
441            Attribute::PrivateCookieKey => ATTR_PRIVATE_COOKIE_KEY,
442            Attribute::PrivilegeExpiry => ATTR_PRIVILEGE_EXPIRY,
443            Attribute::RadiusSecret => ATTR_RADIUS_SECRET,
444            Attribute::RecycledDirectMemberOf => ATTR_RECYCLEDDIRECTMEMBEROF,
445            Attribute::Refers => ATTR_REFERS,
446            Attribute::Replicated => ATTR_REPLICATED,
447            Attribute::Rs256PrivateKeyDer => ATTR_RS256_PRIVATE_KEY_DER,
448            Attribute::S256 => ATTR_S256,
449            Attribute::Scope => ATTR_SCOPE,
450            Attribute::ScimSchemas => ATTR_SCIM_SCHEMAS,
451            Attribute::SendAfter => ATTR_SEND_AFTER,
452            Attribute::SentAt => ATTR_SENT_AT,
453            Attribute::SourceUuid => ATTR_SOURCE_UUID,
454            Attribute::Spn => ATTR_SPN,
455            Attribute::SshPublicKey => ATTR_SSH_PUBLICKEY,
456            Attribute::SudoHost => ATTR_SUDOHOST,
457            Attribute::Supplements => ATTR_SUPPLEMENTS,
458            Attribute::SyncAllowed => ATTR_SYNC_ALLOWED,
459            Attribute::SyncClass => ATTR_SYNC_CLASS,
460            Attribute::SyncCookie => ATTR_SYNC_COOKIE,
461            Attribute::SyncCredentialPortal => ATTR_SYNC_CREDENTIAL_PORTAL,
462            Attribute::SyncExternalId => ATTR_SYNC_EXTERNAL_ID,
463            Attribute::SyncParentUuid => ATTR_SYNC_PARENT_UUID,
464            Attribute::SyncTokenSession => ATTR_SYNC_TOKEN_SESSION,
465            Attribute::SyncYieldAuthority => ATTR_SYNC_YIELD_AUTHORITY,
466            Attribute::Syntax => ATTR_SYNTAX,
467            Attribute::SystemExcludes => ATTR_SYSTEMEXCLUDES,
468            Attribute::SystemMay => ATTR_SYSTEMMAY,
469            Attribute::SystemMust => ATTR_SYSTEMMUST,
470            Attribute::SystemSupplements => ATTR_SYSTEMSUPPLEMENTS,
471            Attribute::Term => ATTR_TERM,
472            Attribute::TotpImport => ATTR_TOTP_IMPORT,
473            Attribute::Uid => ATTR_UID,
474            Attribute::UidNumber => ATTR_UIDNUMBER,
475            Attribute::Unique => ATTR_UNIQUE,
476            Attribute::UnixPassword => ATTR_UNIX_PASSWORD,
477            Attribute::UnixPasswordImport => ATTR_UNIX_PASSWORD_IMPORT,
478            Attribute::UserAuthTokenSession => ATTR_USER_AUTH_TOKEN_SESSION,
479            Attribute::UserId => ATTR_USERID,
480            Attribute::UserPassword => ATTR_USERPASSWORD,
481            Attribute::Uuid => ATTR_UUID,
482            Attribute::Version => ATTR_VERSION,
483            Attribute::WebauthnAttestationCaList => ATTR_WEBAUTHN_ATTESTATION_CA_LIST,
484
485            #[cfg(any(debug_assertions, test, feature = "test"))]
486            Attribute::NonExist => TEST_ATTR_NON_EXIST,
487            #[cfg(any(debug_assertions, test, feature = "test"))]
488            Attribute::TestAttr => TEST_ATTR_TEST_ATTR,
489
490            #[cfg(test)]
491            Attribute::TestAttrA => TEST_ATTR_TEST_ATTR_A,
492            #[cfg(test)]
493            Attribute::TestAttrB => TEST_ATTR_TEST_ATTR_B,
494            #[cfg(test)]
495            Attribute::TestAttrC => TEST_ATTR_TEST_ATTR_C,
496            #[cfg(test)]
497            Attribute::TestAttrD => TEST_ATTR_TEST_ATTR_D,
498
499            #[cfg(any(debug_assertions, test, feature = "test"))]
500            Attribute::Extra => TEST_ATTR_EXTRA,
501            #[cfg(any(debug_assertions, test, feature = "test"))]
502            Attribute::TestNumber => TEST_ATTR_NUMBER,
503            #[cfg(any(debug_assertions, test, feature = "test"))]
504            Attribute::TestNotAllowed => TEST_ATTR_NOTALLOWED,
505
506            #[cfg(not(test))]
507            Attribute::Custom(value) => value.as_str(),
508        }
509    }
510
511    // We allow this because the standard lib from_str is fallible, and we want an infallible version.
512    #[allow(clippy::should_implement_trait)]
513    fn inner_from_str(value: &str) -> Self {
514        // Could this be something like heapless to save allocations? Also gives a way
515        // to limit length of str?
516        match value.to_lowercase().as_str() {
517            ATTR_ACCOUNT => Attribute::Account,
518            ATTR_ACCOUNT_EXPIRE => Attribute::AccountExpire,
519            ATTR_ACCOUNT_VALID_FROM => Attribute::AccountValidFrom,
520            ATTR_ACCOUNT_SOFTLOCK_EXPIRE => Attribute::AccountSoftlockExpire,
521            ATTR_ACP_CREATE_ATTR => Attribute::AcpCreateAttr,
522            ATTR_ACP_CREATE_CLASS => Attribute::AcpCreateClass,
523            ATTR_ACP_ENABLE => Attribute::AcpEnable,
524            ATTR_ACP_MODIFY_CLASS => Attribute::AcpModifyClass,
525            ATTR_ACP_MODIFY_PRESENT_CLASS => Attribute::AcpModifyPresentClass,
526            ATTR_ACP_MODIFY_REMOVE_CLASS => Attribute::AcpModifyRemoveClass,
527            ATTR_ACP_MODIFY_PRESENTATTR => Attribute::AcpModifyPresentAttr,
528            ATTR_ACP_MODIFY_REMOVEDATTR => Attribute::AcpModifyRemovedAttr,
529            ATTR_ACP_RECEIVER => Attribute::AcpReceiver,
530            ATTR_ACP_RECEIVER_GROUP => Attribute::AcpReceiverGroup,
531            ATTR_ACP_SEARCH_ATTR => Attribute::AcpSearchAttr,
532            ATTR_ACP_TARGET_SCOPE => Attribute::AcpTargetScope,
533            ATTR_ALLOW_PRIMARY_CRED_FALLBACK => Attribute::AllowPrimaryCredFallback,
534            ATTR_API_TOKEN_SESSION => Attribute::ApiTokenSession,
535            ATTR_APPLICATION_PASSWORD => Attribute::ApplicationPassword,
536            ATTR_APPLICATION_URL => Attribute::ApplicationUrl,
537            ATTR_ATTESTED_PASSKEYS => Attribute::AttestedPasskeys,
538            ATTR_ATTR => Attribute::Attr,
539            ATTR_ATTRIBUTENAME => Attribute::AttributeName,
540            ATTR_ATTRIBUTETYPE => Attribute::AttributeType,
541            ATTR_AUTH_SESSION_EXPIRY => Attribute::AuthSessionExpiry,
542            ATTR_AUTH_PASSWORD_MINIMUM_LENGTH => Attribute::AuthPasswordMinimumLength,
543            ATTR_BADLIST_PASSWORD => Attribute::BadlistPassword,
544            ATTR_CERTIFICATE => Attribute::Certificate,
545            ATTR_CASCADE_DELETED => Attribute::CascadeDeleted,
546            ATTR_CLAIM => Attribute::Claim,
547            ATTR_CLASS => Attribute::Class,
548            ATTR_CLASSNAME => Attribute::ClassName,
549            ATTR_CN => Attribute::Cn,
550            ATTR_COOKIE_PRIVATE_KEY => Attribute::CookiePrivateKey,
551            ATTR_CREATED_AT_CID => Attribute::CreatedAtCid,
552            ATTR_CREDENTIAL_UPDATE_INTENT_TOKEN => Attribute::CredentialUpdateIntentToken,
553            ATTR_CREDENTIAL_TYPE_MINIMUM => Attribute::CredentialTypeMinimum,
554            ATTR_DENIED_NAME => Attribute::DeniedName,
555            ATTR_DELETE_AFTER => Attribute::DeleteAfter,
556            ATTR_DESCRIPTION => Attribute::Description,
557            ATTR_DIRECTMEMBEROF => Attribute::DirectMemberOf,
558            ATTR_DISPLAYNAME => Attribute::DisplayName,
559            ATTR_DN => Attribute::Dn,
560            ATTR_DOMAIN => Attribute::Domain,
561            ATTR_DOMAIN_ALLOW_EASTER_EGGS => Attribute::DomainAllowEasterEggs,
562            ATTR_DOMAIN_ALLOW_ACCOUNT_RECOVERY => Attribute::DomainAllowAccountRecovery,
563            ATTR_DOMAIN_DISPLAY_NAME => Attribute::DomainDisplayName,
564            ATTR_DOMAIN_DEVELOPMENT_TAINT => Attribute::DomainDevelopmentTaint,
565            ATTR_DOMAIN_LDAP_BASEDN => Attribute::DomainLdapBasedn,
566            ATTR_DOMAIN_NAME => Attribute::DomainName,
567            ATTR_DOMAIN_SSID => Attribute::DomainSsid,
568            ATTR_DOMAIN_TOKEN_KEY => Attribute::DomainTokenKey,
569            ATTR_DOMAIN_UUID => Attribute::DomainUuid,
570            ATTR_DYNGROUP => Attribute::DynGroup,
571            ATTR_DYNGROUP_FILTER => Attribute::DynGroupFilter,
572            ATTR_DYNMEMBER => Attribute::DynMember,
573            ATTR_ENABLED => Attribute::Enabled,
574            ATTR_EMAIL => Attribute::Email,
575            ATTR_EMAIL_ALTERNATIVE => Attribute::EmailAlternative,
576            ATTR_EMAIL_PRIMARY => Attribute::EmailPrimary,
577            ATTR_ENTRYDN => Attribute::EntryDn,
578            ATTR_ENTRY_MANAGED_BY => Attribute::EntryManagedBy,
579            ATTR_ENTRYUUID => Attribute::EntryUuid,
580            ATTR_ES256_PRIVATE_KEY_DER => Attribute::Es256PrivateKeyDer,
581            ATTR_EXCLUDES => Attribute::Excludes,
582            ATTR_FERNET_PRIVATE_KEY_STR => Attribute::FernetPrivateKeyStr,
583            ATTR_GECOS => Attribute::Gecos,
584            ATTR_GIDNUMBER => Attribute::GidNumber,
585            ATTR_GRANT_UI_HINT => Attribute::GrantUiHint,
586            ATTR_GROUP => Attribute::Group,
587            ATTR_HMAC_NAME_HISTORY => Attribute::HmacNameHistory,
588            ATTR_HOME_DIRECTORY => Attribute::HomeDirectory,
589            ATTR_ID_VERIFICATION_ECKEY => Attribute::IdVerificationEcKey,
590            ATTR_IMAGE => Attribute::Image,
591            ATTR_INDEX => Attribute::Index,
592            ATTR_INDEXED => Attribute::Indexed,
593            ATTR_IN_MEMORIAM => Attribute::InMemoriam,
594            ATTR_IPANTHASH => Attribute::IpaNtHash,
595            ATTR_IPASSHPUBKEY => Attribute::IpaSshPubKey,
596            ATTR_JWS_ES256_PRIVATE_KEY => Attribute::JwsEs256PrivateKey,
597            ATTR_KEY_ACTION_ROTATE => Attribute::KeyActionRotate,
598            ATTR_KEY_ACTION_REVOKE => Attribute::KeyActionRevoke,
599            ATTR_KEY_ACTION_IMPORT_JWS_ES256 => Attribute::KeyActionImportJwsEs256,
600            ATTR_KEY_ACTION_IMPORT_JWS_RS256 => Attribute::KeyActionImportJwsRs256,
601            ATTR_KEY_INTERNAL_DATA => Attribute::KeyInternalData,
602            ATTR_KEY_PROVIDER => Attribute::KeyProvider,
603            ATTR_LAST_MODIFIED_CID => Attribute::LastModifiedCid,
604            ATTR_LDAP_ALLOW_UNIX_PW_BIND => Attribute::LdapAllowUnixPwBind,
605            ATTR_LDAP_EMAIL_ADDRESS => Attribute::LdapEmailAddress,
606            ATTR_LDAP_KEYS => Attribute::LdapKeys,
607            ATTR_LDAP_MAX_QUERYABLE_ATTRS => Attribute::LdapMaxQueryableAttrs,
608            ATTR_SSH_PUBLICKEY => Attribute::SshPublicKey,
609            ATTR_LEGALNAME => Attribute::LegalName,
610            ATTR_LINKEDGROUP => Attribute::LinkedGroup,
611            ATTR_LOGINSHELL => Attribute::LoginShell,
612            ATTR_LIMIT_SEARCH_MAX_RESULTS => Attribute::LimitSearchMaxResults,
613            ATTR_LIMIT_SEARCH_MAX_FILTER_TEST => Attribute::LimitSearchMaxFilterTest,
614            ATTR_MAIL => Attribute::Mail,
615            ATTR_MAIL_DESTINATION => Attribute::MailDestination,
616            ATTR_MAY => Attribute::May,
617            ATTR_MEMBER => Attribute::Member,
618            ATTR_MEMBER_CREATE_ONCE => Attribute::MemberCreateOnce,
619            ATTR_MEMBEROF => Attribute::MemberOf,
620            ATTR_MESSAGE_TEMPLATE => Attribute::MessageTemplate,
621            ATTR_MULTIVALUE => Attribute::MultiValue,
622            ATTR_MUST => Attribute::Must,
623            ATTR_NAME => Attribute::Name,
624            ATTR_NAME_HISTORY => Attribute::NameHistory,
625            ATTR_NO_INDEX => Attribute::NoIndex,
626            ATTR_NSUNIQUEID => Attribute::NsUniqueId,
627            ATTR_NSACCOUNTLOCK => Attribute::NsAccountLock,
628            ATTR_OAUTH2_ALLOW_INSECURE_CLIENT_DISABLE_PKCE => {
629                Attribute::OAuth2AllowInsecureClientDisablePkce
630            }
631            ATTR_OAUTH2_ALLOW_LOCALHOST_REDIRECT => Attribute::OAuth2AllowLocalhostRedirect,
632            ATTR_OAUTH2_AUTHORISATION_ENDPOINT => Attribute::OAuth2AuthorisationEndpoint,
633            ATTR_OAUTH2_CLIENT_ID => Attribute::OAuth2ClientId,
634            ATTR_OAUTH2_CLIENT_SECRET => Attribute::OAuth2ClientSecret,
635            ATTR_OAUTH2_CONSENT_SCOPE_MAP => Attribute::OAuth2ConsentScopeMap,
636            ATTR_OAUTH2_DEVICE_FLOW_ENABLE => Attribute::OAuth2DeviceFlowEnable,
637            ATTR_OAUTH2_JWT_LEGACY_CRYPTO_ENABLE => Attribute::OAuth2JwtLegacyCryptoEnable,
638            ATTR_OAUTH2_PREFER_SHORT_USERNAME => Attribute::OAuth2PreferShortUsername,
639            ATTR_OAUTH2_REFRESH_TOKEN_EXPIRY => Attribute::OAuth2RefreshTokenExpiry,
640            ATTR_OAUTH2_REQUEST_SCOPES => Attribute::OAuth2RequestScopes,
641            ATTR_OAUTH2_RS_BASIC_SECRET => Attribute::OAuth2RsBasicSecret,
642            ATTR_OAUTH2_RS_CLAIM_MAP => Attribute::OAuth2RsClaimMap,
643            ATTR_OAUTH2_RS_IMPLICIT_SCOPES => Attribute::OAuth2RsImplicitScopes,
644            ATTR_OAUTH2_RS_NAME => Attribute::OAuth2RsName,
645            ATTR_OAUTH2_RS_ORIGIN => Attribute::OAuth2RsOrigin,
646            ATTR_OAUTH2_RS_ORIGIN_LANDING => Attribute::OAuth2RsOriginLanding,
647            ATTR_OAUTH2_RS_SCOPE_MAP => Attribute::OAuth2RsScopeMap,
648            ATTR_OAUTH2_RS_SUP_SCOPE_MAP => Attribute::OAuth2RsSupScopeMap,
649            ATTR_OAUTH2_RS_TOKEN_KEY => Attribute::OAuth2RsTokenKey,
650            ATTR_OAUTH2_SESSION => Attribute::OAuth2Session,
651            ATTR_OAUTH2_STRICT_REDIRECT_URI => Attribute::OAuth2StrictRedirectUri,
652            ATTR_OAUTH2_TOKEN_ENDPOINT => Attribute::OAuth2TokenEndpoint,
653            ATTR_OAUTH2_ACCOUNT_CREDENTIAL_UUID => Attribute::OAuth2AccountCredentialUuid,
654            ATTR_OAUTH2_ACCOUNT_PROVIDER => Attribute::OAuth2AccountProvider,
655            ATTR_OAUTH2_ACCOUNT_UNIQUE_USER_ID => Attribute::OAuth2AccountUniqueUserId,
656            ATTR_OAUTH2_CONSENT_PROMPT_ENABLE => Attribute::OAuth2ConsentPromptEnable,
657            ATTR_OBJECTCLASS => Attribute::ObjectClass,
658            ATTR_OTHER_NO_INDEX => Attribute::OtherNoIndex,
659            ATTR_PASSKEYS => Attribute::PassKeys,
660            ATTR_PASSWORD_IMPORT => Attribute::PasswordImport,
661            ATTR_PATCH_LEVEL => Attribute::PatchLevel,
662            ATTR_PHANTOM => Attribute::Phantom,
663            ATTR_PRIMARY_CREDENTIAL => Attribute::PrimaryCredential,
664            ATTR_PRIVATE_COOKIE_KEY => Attribute::PrivateCookieKey,
665            ATTR_PRIVILEGE_EXPIRY => Attribute::PrivilegeExpiry,
666            ATTR_PWD_CHANGED_TIME => Attribute::PasswordChangedTime,
667            ATTR_RADIUS_SECRET => Attribute::RadiusSecret,
668            ATTR_RECYCLEDDIRECTMEMBEROF => Attribute::RecycledDirectMemberOf,
669            ATTR_REFERS => Attribute::Refers,
670            ATTR_REPLICATED => Attribute::Replicated,
671            ATTR_RS256_PRIVATE_KEY_DER => Attribute::Rs256PrivateKeyDer,
672            ATTR_S256 => Attribute::S256,
673            ATTR_SCIM_SCHEMAS => Attribute::ScimSchemas,
674            ATTR_SEND_AFTER => Attribute::SendAfter,
675            ATTR_SENT_AT => Attribute::SentAt,
676            ATTR_SCOPE => Attribute::Scope,
677            ATTR_SOURCE_UUID => Attribute::SourceUuid,
678            ATTR_SPN => Attribute::Spn,
679            ATTR_LDAP_SSHPUBLICKEY => Attribute::LdapSshPublicKey,
680            ATTR_SUDOHOST => Attribute::SudoHost,
681            ATTR_SUPPLEMENTS => Attribute::Supplements,
682            ATTR_SYNC_ALLOWED => Attribute::SyncAllowed,
683            ATTR_SYNC_CLASS => Attribute::SyncClass,
684            ATTR_SYNC_COOKIE => Attribute::SyncCookie,
685            ATTR_SYNC_CREDENTIAL_PORTAL => Attribute::SyncCredentialPortal,
686            ATTR_SYNC_EXTERNAL_ID => Attribute::SyncExternalId,
687            ATTR_SYNC_PARENT_UUID => Attribute::SyncParentUuid,
688            ATTR_SYNC_TOKEN_SESSION => Attribute::SyncTokenSession,
689            ATTR_SYNC_YIELD_AUTHORITY => Attribute::SyncYieldAuthority,
690            ATTR_SYNTAX => Attribute::Syntax,
691            ATTR_SYSTEMEXCLUDES => Attribute::SystemExcludes,
692            ATTR_SYSTEMMAY => Attribute::SystemMay,
693            ATTR_SYSTEMMUST => Attribute::SystemMust,
694            ATTR_SYSTEMSUPPLEMENTS => Attribute::SystemSupplements,
695            ATTR_TERM => Attribute::Term,
696            ATTR_TOTP_IMPORT => Attribute::TotpImport,
697            ATTR_UID => Attribute::Uid,
698            ATTR_UIDNUMBER => Attribute::UidNumber,
699            ATTR_UNIQUE => Attribute::Unique,
700            ATTR_UNIX_PASSWORD => Attribute::UnixPassword,
701            ATTR_UNIX_PASSWORD_IMPORT => Attribute::UnixPasswordImport,
702            ATTR_USER_AUTH_TOKEN_SESSION => Attribute::UserAuthTokenSession,
703            ATTR_USERID => Attribute::UserId,
704            ATTR_USERPASSWORD => Attribute::UserPassword,
705            ATTR_UUID => Attribute::Uuid,
706            ATTR_VERSION => Attribute::Version,
707            ATTR_WEBAUTHN_ATTESTATION_CA_LIST => Attribute::WebauthnAttestationCaList,
708
709            #[cfg(any(debug_assertions, test, feature = "test"))]
710            TEST_ATTR_NON_EXIST => Attribute::NonExist,
711            #[cfg(any(debug_assertions, test, feature = "test"))]
712            TEST_ATTR_TEST_ATTR => Attribute::TestAttr,
713
714            #[cfg(test)]
715            TEST_ATTR_TEST_ATTR_A => Attribute::TestAttrA,
716            #[cfg(test)]
717            TEST_ATTR_TEST_ATTR_B => Attribute::TestAttrB,
718            #[cfg(test)]
719            TEST_ATTR_TEST_ATTR_C => Attribute::TestAttrC,
720            #[cfg(test)]
721            TEST_ATTR_TEST_ATTR_D => Attribute::TestAttrD,
722
723            #[cfg(any(debug_assertions, test, feature = "test"))]
724            TEST_ATTR_EXTRA => Attribute::Extra,
725            #[cfg(any(debug_assertions, test, feature = "test"))]
726            TEST_ATTR_NUMBER => Attribute::TestNumber,
727            #[cfg(any(debug_assertions, test, feature = "test"))]
728            TEST_ATTR_NOTALLOWED => Attribute::TestNotAllowed,
729
730            #[cfg(not(test))]
731            _ => Attribute::Custom(AttrString::from(value)),
732            // Allowed only in tests
733            #[allow(clippy::unreachable)]
734            #[cfg(test)]
735            _ => {
736                unreachable!(
737                    "Check that you've implemented the Attribute conversion for {:?}",
738                    value
739                );
740            }
741        }
742    }
743}
744
745impl fmt::Display for Attribute {
746    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
747        write!(f, "{}", self.as_str())
748    }
749}
750
751impl From<Attribute> for String {
752    fn from(attr: Attribute) -> String {
753        attr.to_string()
754    }
755}
756
757/// Sub attributes are a component of SCIM, allowing tagged sub properties of a complex
758/// attribute to be accessed.
759#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash, ToSchema)]
760#[serde(rename_all = "lowercase", try_from = "&str", into = "AttrString")]
761pub enum SubAttribute {
762    /// Denotes a primary value.
763    Primary,
764    /// The type of value
765    Type,
766    /// The data associated to a value
767    Value,
768
769    #[cfg(not(test))]
770    #[schema(value_type = String)]
771    Custom(AttrString),
772}
773
774impl fmt::Display for SubAttribute {
775    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
776        write!(f, "{}", self.as_str())
777    }
778}
779
780impl From<SubAttribute> for AttrString {
781    fn from(val: SubAttribute) -> Self {
782        AttrString::from(val.as_str())
783    }
784}
785
786impl From<&str> for SubAttribute {
787    fn from(value: &str) -> Self {
788        Self::inner_from_str(value)
789    }
790}
791
792impl FromStr for SubAttribute {
793    type Err = Infallible;
794
795    fn from_str(value: &str) -> Result<Self, Self::Err> {
796        Ok(Self::inner_from_str(value))
797    }
798}
799
800impl SubAttribute {
801    pub fn as_str(&self) -> &str {
802        match self {
803            SubAttribute::Primary => SUB_ATTR_PRIMARY,
804            SubAttribute::Type => SUB_ATTR_TYPE,
805            SubAttribute::Value => SUB_ATTR_VALUE,
806            #[cfg(not(test))]
807            SubAttribute::Custom(s) => s,
808        }
809    }
810
811    // We allow this because the standard lib from_str is fallible, and we want an infallible version.
812    #[allow(clippy::should_implement_trait)]
813    fn inner_from_str(value: &str) -> Self {
814        // Could this be something like heapless to save allocations? Also gives a way
815        // to limit length of str?
816        match value.to_lowercase().as_str() {
817            SUB_ATTR_PRIMARY => SubAttribute::Primary,
818            SUB_ATTR_TYPE => SubAttribute::Type,
819            SUB_ATTR_VALUE => SubAttribute::Value,
820
821            #[cfg(not(test))]
822            _ => SubAttribute::Custom(AttrString::from(value)),
823
824            // Allowed only in tests
825            #[allow(clippy::unreachable)]
826            #[cfg(test)]
827            _ => {
828                unreachable!(
829                    "Check that you've implemented the SubAttribute conversion for {:?}",
830                    value
831                );
832            }
833        }
834    }
835}
836
837#[cfg(test)]
838mod test {
839    use super::Attribute;
840
841    #[test]
842    fn test_valueattribute_from_str() {
843        assert_eq!(Attribute::Uuid, Attribute::from("UUID"));
844        assert_eq!(Attribute::Uuid, Attribute::from("UuiD"));
845        assert_eq!(Attribute::Uuid, Attribute::from("uuid"));
846    }
847
848    #[test]
849    fn test_valueattribute_as_str() {
850        assert_eq!(Attribute::Class.as_str(), "class");
851        assert_eq!(Attribute::Class.to_string(), "class".to_string());
852    }
853
854    #[test]
855    // this ensures we cover both ends of the conversion to/from string-types
856    fn test_valueattribute_round_trip() {
857        use enum_iterator::all;
858        let the_list = all::<Attribute>().collect::<Vec<_>>();
859        for attr in the_list {
860            let attr2 = Attribute::from(attr.as_str());
861            assert!(
862                attr == attr2,
863                "Round-trip failed for {attr} <=> {attr2} check you've implemented a from and to string"
864            );
865        }
866    }
867}