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