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