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