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