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