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