001/* 002 * Copyright 2020-2024 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright 2020-2024 Ping Identity Corporation 007 * 008 * Licensed under the Apache License, Version 2.0 (the "License"); 009 * you may not use this file except in compliance with the License. 010 * You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, software 015 * distributed under the License is distributed on an "AS IS" BASIS, 016 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 017 * See the License for the specific language governing permissions and 018 * limitations under the License. 019 */ 020/* 021 * Copyright (C) 2020-2024 Ping Identity Corporation 022 * 023 * This program is free software; you can redistribute it and/or modify 024 * it under the terms of the GNU General Public License (GPLv2 only) 025 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 026 * as published by the Free Software Foundation. 027 * 028 * This program is distributed in the hope that it will be useful, 029 * but WITHOUT ANY WARRANTY; without even the implied warranty of 030 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 031 * GNU General Public License for more details. 032 * 033 * You should have received a copy of the GNU General Public License 034 * along with this program; if not, see <http://www.gnu.org/licenses>. 035 */ 036package com.unboundid.ldap.sdk.unboundidds; 037 038 039 040import java.io.Serializable; 041import java.util.ArrayList; 042import java.util.Collections; 043import java.util.Date; 044import java.util.LinkedHashMap; 045import java.util.List; 046import java.util.Map; 047 048import com.unboundid.ldap.sdk.Entry; 049import com.unboundid.ldap.sdk.LDAPException; 050import com.unboundid.ldap.sdk.LDAPInterface; 051import com.unboundid.ldap.sdk.ResultCode; 052import com.unboundid.ldap.sdk.SearchResultEntry; 053import com.unboundid.ldap.sdk.unboundidds.controls.RecentLoginHistory; 054import com.unboundid.ldap.sdk.unboundidds.extensions. 055 PasswordPolicyStateAccountUsabilityError; 056import com.unboundid.ldap.sdk.unboundidds.extensions. 057 PasswordPolicyStateAccountUsabilityNotice; 058import com.unboundid.ldap.sdk.unboundidds.extensions. 059 PasswordPolicyStateAccountUsabilityWarning; 060import com.unboundid.ldap.sdk.unboundidds.extensions. 061 PasswordPolicyStateExtendedRequest; 062import com.unboundid.ldap.sdk.unboundidds.extensions.PasswordQualityRequirement; 063import com.unboundid.util.Debug; 064import com.unboundid.util.NotMutable; 065import com.unboundid.util.NotNull; 066import com.unboundid.util.Nullable; 067import com.unboundid.util.StaticUtils; 068import com.unboundid.util.ThreadSafety; 069import com.unboundid.util.ThreadSafetyLevel; 070import com.unboundid.util.json.JSONObject; 071import com.unboundid.util.json.JSONString; 072import com.unboundid.util.json.JSONValue; 073 074import static com.unboundid.ldap.sdk.unboundidds.PasswordPolicyStateJSONField.*; 075import static com.unboundid.ldap.sdk.unboundidds.UnboundIDDSMessages.*; 076 077 078 079/** 080 * This class provides support for reading and decoding the value of the 081 * {@code ds-pwp-state-json} virtual attribute, which holds information about a 082 * user's password policy state. 083 * <BR> 084 * <BLOCKQUOTE> 085 * <B>NOTE:</B> This class, and other classes within the 086 * {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only 087 * supported for use against Ping Identity, UnboundID, and 088 * Nokia/Alcatel-Lucent 8661 server products. These classes provide support 089 * for proprietary functionality or for external specifications that are not 090 * considered stable or mature enough to be guaranteed to work in an 091 * interoperable way with other types of LDAP servers. 092 * </BLOCKQUOTE> 093 * 094 * 095 * @see ModifiablePasswordPolicyStateJSON 096 * @see PasswordPolicyStateExtendedRequest 097 * @see PasswordPolicyStateJSONField 098 */ 099@NotMutable() 100@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE) 101public final class PasswordPolicyStateJSON 102 implements Serializable 103{ 104 /** 105 * The name of the operational attribute that holds a JSON representation of a 106 * user's password policy state. 107 */ 108 @NotNull public static final String PASSWORD_POLICY_STATE_JSON_ATTRIBUTE = 109 "ds-pwp-state-json"; 110 111 112 113 /** 114 * The name of the field that will be used to indicate whether a password 115 * quality requirement applies to add operations. 116 */ 117 @NotNull private static final String REQUIREMENT_FIELD_APPLIES_TO_ADD = 118 "applies-to-add"; 119 120 121 122 /** 123 * The name of the field that will be used to indicate whether a password 124 * quality requirement applies to administrative password resets. 125 */ 126 @NotNull private static final String 127 REQUIREMENT_FIELD_APPLIES_TO_ADMIN_RESET = 128 "applies-to-administrative-reset"; 129 130 131 132 /** 133 * The name of the field that will be used to indicate whether a password 134 * quality requirement applies to bind operations. 135 */ 136 @NotNull private static final String REQUIREMENT_FIELD_APPLIES_TO_BIND = 137 "applies-to-bind"; 138 139 140 141 /** 142 * The name of the field that will be used to indicate whether a password 143 * quality requirement applies to self password changes. 144 */ 145 @NotNull private static final String 146 REQUIREMENT_FIELD_APPLIES_TO_SELF_CHANGE = "applies-to-self-change"; 147 148 149 150 /** 151 * The name of the field that will be used to hold the set of client-side 152 * validation properties. 153 */ 154 @NotNull private static final String 155 REQUIREMENT_FIELD_CLIENT_SIDE_VALIDATION_PROPERTIES = 156 "client-side-validation-properties"; 157 158 159 160 /** 161 * The name of the field that will be used to hold the name of a client-side 162 * validation property. 163 */ 164 @NotNull private static final String 165 REQUIREMENT_FIELD_CLIENT_SIDE_VALIDATION_PROPERTY_NAME = "name"; 166 167 168 169 /** 170 * The name of the field that will be used to hold the value of a client-side 171 * validation property. 172 */ 173 @NotNull private static final String 174 REQUIREMENT_FIELD_CLIENT_SIDE_VALIDATION_PROPERTY_VALUE = "value"; 175 176 177 178 /** 179 * The name of the field that will be used to hold the name of the client-side 180 * validation type for a password quality requirement. 181 */ 182 @NotNull private static final String 183 REQUIREMENT_FIELD_CLIENT_SIDE_VALIDATION_TYPE = 184 "client-side-validation-type"; 185 186 187 188 /** 189 * The name of the field that will be used to hold the description component 190 * of a password quality requirement. 191 */ 192 @NotNull private static final String REQUIREMENT_FIELD_DESCRIPTION = 193 "description"; 194 195 196 197 /** 198 * The name of the field that will be used to hold the message component of an 199 * account usability error, warning, or notice. 200 */ 201 @NotNull private static final String USABILITY_FIELD_MESSAGE = "message"; 202 203 204 205 /** 206 * The name of the field that will be used to hold the integer version of 207 * the identifier for of an account usability error, warning, or notice. 208 */ 209 @NotNull private static final String USABILITY_FIELD_TYPE_ID = "type-id"; 210 211 212 213 /** 214 * The name of the field that will be used to hold the name of the identifier 215 * for of an account usability error, warning, or notice. 216 */ 217 @NotNull private static final String USABILITY_FIELD_TYPE_NAME = "type-name"; 218 219 220 221 /** 222 * The name of the field that will be used to hold the name of a password 223 * storage scheme for a password that is encoded with non-current settings. 224 */ 225 @NotNull private static final String NON_CURRENT_ENCODING_FIELD_SCHEME = 226 "scheme"; 227 228 229 230 /** 231 * The name of the field that will be used to hold the set of explanations for 232 * a password that is encoded with non-current settings. 233 */ 234 @NotNull private static final String NON_CURRENT_ENCODING_FIELD_EXPLANATIONS = 235 "explanations"; 236 237 238 239 /** 240 * The serial version UID for this serializable class. 241 */ 242 private static final long serialVersionUID = -3953182526241789456L; 243 244 245 246 247 // The JSON object that contains the password policy state information. 248 @NotNull private final JSONObject passwordPolicyStateObject; 249 250 251 252 /** 253 * Creates a new instance of this object from the provided JSON object. 254 * 255 * @param passwordPolicyStateObject The JSON object containing the encoded 256 * password policy state. 257 */ 258 public PasswordPolicyStateJSON( 259 @NotNull final JSONObject passwordPolicyStateObject) 260 { 261 this.passwordPolicyStateObject = passwordPolicyStateObject; 262 } 263 264 265 266 /** 267 * Attempts to retrieve and decode the password policy state information for 268 * the specified user. 269 * 270 * @param connection The connection to use to communicate with the server. 271 * It must not be {@code null}, and it must be established 272 * and authenticated as an account with permission to 273 * access the target user's password policy state 274 * information. 275 * @param userDN The DN of the user for whom to retrieve the password 276 * policy state. It must not be {@code null}. 277 * 278 * @return The password policy state information for the specified user, or 279 * {@code null} because no password policy state information is 280 * available for the user. 281 * 282 * @throws LDAPException If a problem is encountered while trying to 283 * retrieve the user's entry or decode the password 284 * policy state JSON object. 285 */ 286 @Nullable() 287 public static PasswordPolicyStateJSON get( 288 @NotNull final LDAPInterface connection, 289 @NotNull final String userDN) 290 throws LDAPException 291 { 292 final SearchResultEntry userEntry = connection.getEntry(userDN, 293 PASSWORD_POLICY_STATE_JSON_ATTRIBUTE); 294 if (userEntry == null) 295 { 296 throw new LDAPException(ResultCode.NO_SUCH_OBJECT, 297 ERR_PW_POLICY_STATE_JSON_GET_NO_SUCH_USER.get(userDN)); 298 } 299 300 return get(userEntry); 301 } 302 303 304 305 /** 306 * Attempts to retrieve and decode the password policy state information from 307 * the provided user entry. 308 * 309 * @param userEntry The entry for the user for whom to obtain the password 310 * policy state information. It must not be {@code null}. 311 * 312 * @return The password policy state information from the provided user 313 * entry, or {@code null} if no password policy state information is 314 * available for the user. 315 * 316 * @throws LDAPException If a problem is encountered while trying to decode 317 * the password policy state JSON object. 318 */ 319 @Nullable() 320 public static PasswordPolicyStateJSON get(@NotNull final Entry userEntry) 321 throws LDAPException 322 { 323 final String valueString = 324 userEntry.getAttributeValue(PASSWORD_POLICY_STATE_JSON_ATTRIBUTE); 325 if (valueString == null) 326 { 327 return null; 328 } 329 330 final JSONObject jsonObject; 331 try 332 { 333 jsonObject = new JSONObject(valueString); 334 } 335 catch (final Exception e) 336 { 337 Debug.debugException(e); 338 throw new LDAPException(ResultCode.DECODING_ERROR, 339 ERR_PW_POLICY_STATE_JSON_GET_CANNOT_DECODE.get( 340 PASSWORD_POLICY_STATE_JSON_ATTRIBUTE, userEntry.getDN()), 341 e); 342 } 343 344 return new PasswordPolicyStateJSON(jsonObject); 345 } 346 347 348 349 /** 350 * Retrieves the JSON object that contains the encoded password policy state 351 * information. 352 * 353 * @return The JSON object that contains the encoded password policy state 354 * information. 355 */ 356 @NotNull() 357 public JSONObject getPasswordPolicyStateJSONObject() 358 { 359 return passwordPolicyStateObject; 360 } 361 362 363 364 /** 365 * Retrieves the DN of the entry that defines the password policy that governs 366 * the associated user. 367 * 368 * @return The DN of the entry that defines hte password policy that governs 369 * the associated user, or {@code null} if this was not included in 370 * the password policy state JSON object. 371 */ 372 @Nullable() 373 public String getPasswordPolicyDN() 374 { 375 return passwordPolicyStateObject.getFieldAsString( 376 PASSWORD_POLICY_DN.getFieldName()); 377 } 378 379 380 381 /** 382 * Retrieves the value of a flag that indicates whether the user's account is 383 * in a state that the server considers usable. 384 * 385 * @return {@code Boolean.TRUE} if the account is in a usable state, 386 * {@code Boolean.FALSE} if the account is not in a usable state, or 387 * {@code null} if this flag was not included in the password policy 388 * state JSON object. 389 */ 390 @Nullable() 391 public Boolean getAccountIsUsable() 392 { 393 return passwordPolicyStateObject.getFieldAsBoolean( 394 ACCOUNT_IS_USABLE.getFieldName()); 395 } 396 397 398 399 /** 400 * Retrieves a list of information about any error conditions that may 401 * affect usability of the user's account. 402 * 403 * @return A list of information about any error conditions that may affect 404 * the usability of the user's account. The returned list may be 405 * empty if there are no account usability errors or if this was not 406 * included in the password policy state JSON object. 407 */ 408 @NotNull() 409 public List<PasswordPolicyStateAccountUsabilityError> 410 getAccountUsabilityErrors() 411 { 412 final List<PasswordPolicyStateAccountUsabilityError> errors = 413 new ArrayList<>(); 414 final List<JSONValue> values = passwordPolicyStateObject.getFieldAsArray( 415 ACCOUNT_USABILITY_ERRORS.getFieldName()); 416 if (values != null) 417 { 418 for (final JSONValue v : values) 419 { 420 if (v instanceof JSONObject) 421 { 422 final JSONObject o = (JSONObject) v; 423 final String typeName = o.getFieldAsString(USABILITY_FIELD_TYPE_NAME); 424 final Integer typeID = o.getFieldAsInteger(USABILITY_FIELD_TYPE_ID); 425 final String message = o.getFieldAsString(USABILITY_FIELD_MESSAGE); 426 if ((typeName != null) && (typeID != null)) 427 { 428 errors.add(new PasswordPolicyStateAccountUsabilityError(typeID, 429 typeName, message)); 430 } 431 } 432 } 433 } 434 435 return Collections.unmodifiableList(errors); 436 } 437 438 439 440 /** 441 * Retrieves a list of information about any warning conditions that may soon 442 * affect usability of the user's account. 443 * 444 * @return A list of information about any warning conditions that may soon 445 * affect the usability of the user's account. The returned list may 446 * be empty if there are no account usability warnings or if this was 447 * not included in the password policy state JSON object. 448 */ 449 @NotNull() 450 public List<PasswordPolicyStateAccountUsabilityWarning> 451 getAccountUsabilityWarnings() 452 { 453 final List<PasswordPolicyStateAccountUsabilityWarning> warnings = 454 new ArrayList<>(); 455 final List<JSONValue> values = passwordPolicyStateObject.getFieldAsArray( 456 ACCOUNT_USABILITY_WARNINGS.getFieldName()); 457 if (values != null) 458 { 459 for (final JSONValue v : values) 460 { 461 if (v instanceof JSONObject) 462 { 463 final JSONObject o = (JSONObject) v; 464 final String typeName = o.getFieldAsString(USABILITY_FIELD_TYPE_NAME); 465 final Integer typeID = o.getFieldAsInteger(USABILITY_FIELD_TYPE_ID); 466 final String message = o.getFieldAsString(USABILITY_FIELD_MESSAGE); 467 if ((typeName != null) && (typeID != null)) 468 { 469 warnings.add(new PasswordPolicyStateAccountUsabilityWarning(typeID, 470 typeName, message)); 471 } 472 } 473 } 474 } 475 476 return Collections.unmodifiableList(warnings); 477 } 478 479 480 481 /** 482 * Retrieves a list of information about any notices related to the usability 483 * of the user's account. 484 * 485 * @return A list of information about any notices related to the usability 486 * of the user's account. The returned list may be empty if there 487 * are no account usability notices or if this was not included in 488 * the password policy state JSON object. 489 */ 490 @NotNull() 491 public List<PasswordPolicyStateAccountUsabilityNotice> 492 getAccountUsabilityNotices() 493 { 494 final List<PasswordPolicyStateAccountUsabilityNotice> notices = 495 new ArrayList<>(); 496 final List<JSONValue> values = passwordPolicyStateObject.getFieldAsArray( 497 ACCOUNT_USABILITY_NOTICES.getFieldName()); 498 if (values != null) 499 { 500 for (final JSONValue v : values) 501 { 502 if (v instanceof JSONObject) 503 { 504 final JSONObject o = (JSONObject) v; 505 final String typeName = o.getFieldAsString(USABILITY_FIELD_TYPE_NAME); 506 final Integer typeID = o.getFieldAsInteger(USABILITY_FIELD_TYPE_ID); 507 final String message = o.getFieldAsString(USABILITY_FIELD_MESSAGE); 508 if ((typeName != null) && (typeID != null)) 509 { 510 notices.add(new PasswordPolicyStateAccountUsabilityNotice(typeID, 511 typeName, message)); 512 } 513 } 514 } 515 } 516 517 return Collections.unmodifiableList(notices); 518 } 519 520 521 522 /** 523 * Retrieves the value of a flag that indicates whether the user's account 524 * contains at least one static password. 525 * 526 * @return {@code Boolean.TRUE} if the account has at least one static 527 * password, {@code Boolean.FALSE} if the account does not have any 528 * static password, or {@code null} if this flag was not included in 529 * the password policy state JSON object. 530 */ 531 @Nullable() 532 public Boolean getHasStaticPassword() 533 { 534 return passwordPolicyStateObject.getFieldAsBoolean( 535 HAS_STATIC_PASSWORD.getFieldName()); 536 } 537 538 539 540 /** 541 * Retrieves the time that the user's password was last changed. 542 * 543 * @return The time that the user's password was last changed, or 544 * {@code null} if this was not included in the password policy state 545 * JSON object. 546 */ 547 @Nullable() 548 public Date getPasswordChangedTime() 549 { 550 return getDate(PASSWORD_CHANGED_TIME); 551 } 552 553 554 555 /** 556 * Retrieves the length of time in seconds that has passed since the user's 557 * password was last changed. 558 * 559 * @return The length of time in seconds that has passed since the user's 560 * password was last changed, or {@code null} if this was not 561 * included in the password policy state JSON object. 562 */ 563 @Nullable() 564 public Integer getSecondsSincePasswordChange() 565 { 566 return passwordPolicyStateObject.getFieldAsInteger( 567 SECONDS_SINCE_PASSWORD_CHANGE.getFieldName()); 568 } 569 570 571 572 /** 573 * Retrieves the value of a flag that indicates whether the user's account has 574 * been administratively disabled. 575 * 576 * @return {@code Boolean.TRUE} if the account has been administratively 577 * disabled, {@code Boolean.FALSE} if the account has not been 578 * administratively disabled, or {@code null} if this flag was not 579 * included in the password policy state JSON object. 580 */ 581 @Nullable() 582 public Boolean getAccountIsDisabled() 583 { 584 return passwordPolicyStateObject.getFieldAsBoolean( 585 ACCOUNT_IS_DISABLED.getFieldName()); 586 } 587 588 589 590 /** 591 * Retrieves the value of a flag that indicates whether the user's account is 592 * not yet active because it has an activation time that is in the future. 593 * 594 * @return {@code Boolean.TRUE} if the account is not yet active, 595 * {@code Boolean.FALSE} if the account either does not have an 596 * activation time or if that time has already passed, or 597 * {@code null} if this flag was not included in the password policy 598 * state JSON object. 599 */ 600 @Nullable() 601 public Boolean getAccountIsNotYetActive() 602 { 603 return passwordPolicyStateObject.getFieldAsBoolean( 604 ACCOUNT_IS_NOT_YET_ACTIVE.getFieldName()); 605 } 606 607 608 609 /** 610 * Retrieves the time that the user's account became (or will become) active. 611 * 612 * @return The time that the user's account became (or will become) active, 613 * or {@code null} if this was not included in the password policy 614 * state JSON object. 615 */ 616 @Nullable() 617 public Date getAccountActivationTime() 618 { 619 return getDate(ACCOUNT_ACTIVATION_TIME); 620 } 621 622 623 624 /** 625 * Retrieves the length of time in seconds until the user's account will 626 * become active. 627 * 628 * @return The length of time in seconds until the user's account will become 629 * active, or {@code null} if this was not included in the password 630 * policy state JSON object (e.g., because the user does not have an 631 * activation time in the future). 632 */ 633 @Nullable() 634 public Integer getSecondsUntilAccountActivation() 635 { 636 return passwordPolicyStateObject.getFieldAsInteger( 637 SECONDS_UNTIL_ACCOUNT_ACTIVATION.getFieldName()); 638 } 639 640 641 642 /** 643 * Retrieves the length of time in seconds since the user's account became 644 * active. 645 * 646 * @return The length of time in seconds since the user's account became 647 * active, or {@code null} if this was not included in the password 648 * policy state JSON object (e.g., because the user does not have an 649 * activation time in the past). 650 */ 651 @Nullable() 652 public Integer getSecondsSinceAccountActivation() 653 { 654 return passwordPolicyStateObject.getFieldAsInteger( 655 SECONDS_SINCE_ACCOUNT_ACTIVATION.getFieldName()); 656 } 657 658 659 660 /** 661 * Retrieves the value of a flag that indicates whether the user's account is 662 * expired. 663 * 664 * @return {@code Boolean.TRUE} if the account is expired, 665 * {@code Boolean.FALSE} if the account is not expired, or 666 * {@code null} if this flag was not included in the password policy 667 * state JSON object. 668 */ 669 @Nullable() 670 public Boolean getAccountIsExpired() 671 { 672 return passwordPolicyStateObject.getFieldAsBoolean( 673 ACCOUNT_IS_EXPIRED.getFieldName()); 674 } 675 676 677 678 /** 679 * Retrieves the time that the user's account will (or did) expire. 680 * 681 * @return The time that the user's account will (or did) expire, or 682 * {@code null} if this was not included in the password policy state 683 * JSON object. 684 */ 685 @Nullable() 686 public Date getAccountExpirationTime() 687 { 688 return getDate(ACCOUNT_EXPIRATION_TIME); 689 } 690 691 692 693 /** 694 * Retrieves the length of time in seconds until the user's account will 695 * expire. 696 * 697 * @return The length of time in seconds until the user's account will 698 * expire, or {@code null} if this was not included in the password 699 * policy state JSON object (e.g., because the user does not have an 700 * expiration time in the future). 701 */ 702 @Nullable() 703 public Integer getSecondsUntilAccountExpiration() 704 { 705 return passwordPolicyStateObject.getFieldAsInteger( 706 SECONDS_UNTIL_ACCOUNT_EXPIRATION.getFieldName()); 707 } 708 709 710 711 /** 712 * Retrieves the length of time in seconds since the user's account expired. 713 * 714 * @return The length of time in seconds since the user's account expired, 715 * or {@code null} if this was not included in the password policy 716 * state JSON object (e.g., because the user does not have an 717 * expiration time in the past). 718 */ 719 @Nullable() 720 public Integer getSecondsSinceAccountExpiration() 721 { 722 return passwordPolicyStateObject.getFieldAsInteger( 723 SECONDS_SINCE_ACCOUNT_EXPIRATION.getFieldName()); 724 } 725 726 727 728 /** 729 * Retrieves the value of a flag that indicates whether the user's password is 730 * expired. 731 * 732 * @return {@code Boolean.TRUE} if the password is expired, 733 * {@code Boolean.FALSE} if the password is not expired, or 734 * {@code null} if this flag was not included in the password policy 735 * state JSON object. 736 */ 737 @Nullable() 738 public Boolean getPasswordIsExpired() 739 { 740 return passwordPolicyStateObject.getFieldAsBoolean( 741 PASSWORD_IS_EXPIRED.getFieldName()); 742 } 743 744 745 746 /** 747 * Retrieves the maximum length of time in seconds after a password change 748 * that the user is allowed to keep using that password. 749 * 750 * @return The maximum length of time in seconds after a password change that 751 * the user is allowed to keep using that password, or {@code null} 752 * if this flag was not included in the password policy state JSON 753 * object (e.g., because password expiration is not configured in the 754 * password policy that governs the user). 755 */ 756 @Nullable() 757 public Integer getMaximumPasswordAgeSeconds() 758 { 759 return passwordPolicyStateObject.getFieldAsInteger( 760 MAXIMUM_PASSWORD_AGE_SECONDS.getFieldName()); 761 } 762 763 764 765 /** 766 * Retrieves the time that the user's password will (or did) expire. 767 * 768 * @return The time that the user's password will (or did) expire, or 769 * {@code null} if this was not included in the password policy state 770 * JSON object (e.g., because password expiration is not configured 771 * in the password policy that governs the user). 772 */ 773 @Nullable() 774 public Date getPasswordExpirationTime() 775 { 776 return getDate(PASSWORD_EXPIRATION_TIME); 777 } 778 779 780 781 /** 782 * Retrieves the length of time in seconds until the user's password will 783 * expire. 784 * 785 * @return The length of time in seconds until the user's password will 786 * expire, or {@code null} if this was not included in the password 787 * policy state JSON object (e.g., because password expiration is not 788 * configured in the password policy that governs the user, or 789 * because the user's password is already expired). 790 */ 791 @Nullable() 792 public Integer getSecondsUntilPasswordExpiration() 793 { 794 return passwordPolicyStateObject.getFieldAsInteger( 795 SECONDS_UNTIL_PASSWORD_EXPIRATION.getFieldName()); 796 } 797 798 799 800 /** 801 * Retrieves the length of time in seconds since the user's password expired. 802 * 803 * @return The length of time in seconds since the user's password expired, 804 * or {@code null} if this was not included in the password policy 805 * state JSON object (e.g., because password expiration is not 806 * configured in the password policy that governs the user, or 807 * because the user's password is not expired). 808 */ 809 @Nullable() 810 public Integer getSecondsSincePasswordExpiration() 811 { 812 return passwordPolicyStateObject.getFieldAsInteger( 813 SECONDS_SINCE_PASSWORD_EXPIRATION.getFieldName()); 814 } 815 816 817 818 /** 819 * Retrieves the length of time in seconds before an upcoming password 820 * expiration that the user will be eligible to start receving warnings about 821 * that expiration. 822 * 823 * @return The length of time in seconds before an upcoming password 824 * expiration that the user will be eligible to start receiving 825 * messages about that expiration, or {@code null} if this was not 826 * included in the password policy state JSON object (e.g., because 827 * password expiration is not configured in the password policy that 828 * governs the user). 829 */ 830 @Nullable() 831 public Integer getPasswordExpirationWarningIntervalSeconds() 832 { 833 return passwordPolicyStateObject.getFieldAsInteger( 834 PASSWORD_EXPIRATION_WARNING_INTERVAL_SECONDS.getFieldName()); 835 } 836 837 838 839 /** 840 * Retrieves the value of a flag that indicates whether the server will allow 841 * a user's password to expire even if they have not yet received any warnings 842 * about an upcoming expiration. 843 * 844 * @return {@code Boolean.TRUE} if the server will allow a user's password to 845 * expire even if they have not been warned about an upcoming 846 * expiration, {@code Boolean.FALSE} if the server will ensure that 847 * the user receives at least one warning before expiring the 848 * password, or {@code null} if this flag was not included in the 849 * password policy state JSON object (e.g., because password 850 * expiration is not configured in the password policy that governs 851 * the user). 852 */ 853 @Nullable() 854 public Boolean getExpirePasswordsWithoutWarning() 855 { 856 return passwordPolicyStateObject.getFieldAsBoolean( 857 EXPIRE_PASSWORDS_WITHOUT_WARNING.getFieldName()); 858 } 859 860 861 862 /** 863 * Retrieves the value of a flag that indicates whether the user has 864 * received at least one warning about an upcoming password expiration. 865 * 866 * @return {@code Boolean.TRUE} if the user has received at least one warning 867 * about an upcoming password expiration, {@code Boolean.FALSE} if 868 * the user has not been warned about an upcoming password 869 * expiration, or {@code null} if this flag was not included in the 870 * password policy state JSON object (e.g., because password 871 * expiration is not configured in the password policy that governs 872 * the user). 873 */ 874 @Nullable() 875 public Boolean getPasswordExpirationWarningIssued() 876 { 877 return passwordPolicyStateObject.getFieldAsBoolean( 878 PASSWORD_EXPIRATION_WARNING_ISSUED.getFieldName()); 879 } 880 881 882 883 /** 884 * Retrieves the time that the user will be eligible to receive (or the time 885 * that the user first received) a warning about an upcoming password 886 * expiration. 887 * 888 * @return The time that the user will be eligible to receive (or the time 889 * that the user first received) a warning about an upcoming password 890 * expiration, or {@code null} if this was not included in the 891 * password policy state JSON object (e.g., because password 892 * expiration is not configured in the password policy that governs 893 * the user). 894 */ 895 @Nullable() 896 public Date getPasswordExpirationWarningTime() 897 { 898 return getDate(PASSWORD_EXPIRATION_WARNING_TIME); 899 } 900 901 902 903 /** 904 * Retrieves the length of time in seconds until the user will be eligible to 905 * receive a warning about an upcoming password expiration. 906 * 907 * @return The length of time in seconds until the user will be eligible to 908 * receive a warning about an upcoming password expiration, or 909 * {@code null} if this was not included in the password policy state 910 * JSON object (e.g., because password expiration is not configured 911 * in the password policy that governs the user, or because the user 912 * has already been warned about an upcoming expiration). 913 */ 914 @Nullable() 915 public Integer getSecondsUntilPasswordExpirationWarning() 916 { 917 return passwordPolicyStateObject.getFieldAsInteger( 918 SECONDS_UNTIL_PASSWORD_EXPIRATION_WARNING.getFieldName()); 919 } 920 921 922 923 /** 924 * Retrieves the length of time in seconds since the user received the first 925 * warning about an upcoming password expiration. 926 * 927 * @return The length of time in seconds since the user received the first 928 * warning about an upcoming password expiration, or {@code null} if 929 * this was not included in the password policy state JSON object 930 * (e.g., because password expiration is not configured in the 931 * password policy that governs the user, or because the user has 932 * not yet been warned about an upcoming expiration). 933 */ 934 @Nullable() 935 public Integer getSecondsSincePasswordExpirationWarning() 936 { 937 return passwordPolicyStateObject.getFieldAsInteger( 938 SECONDS_SINCE_PASSWORD_EXPIRATION_WARNING.getFieldName()); 939 } 940 941 942 943 /** 944 * Retrieves the value of a flag that indicates whether the user account is 945 * currently locked as a result of too many failed authentication attempts. 946 * 947 * @return {@code Boolean.TRUE} if the user account is locked as a result of 948 * too many failed authentication attempts, {@code Boolean.FALSE} if 949 * the user account is not locked because of too many failed 950 * authentication attempts, or {@code null} if this flag was not 951 * included in the password policy state JSON object. 952 */ 953 @Nullable() 954 public Boolean getAccountIsFailureLocked() 955 { 956 return passwordPolicyStateObject.getFieldAsBoolean( 957 ACCOUNT_IS_FAILURE_LOCKED.getFieldName()); 958 } 959 960 961 962 /** 963 * Retrieves the number of consecutive failed authentication attempts that are 964 * required to lock the user's account. 965 * 966 * @return The number of consecutive failed authentication attempts that are 967 * required to lock the user's account, or {@code null} if this was 968 * not included in the password policy state JSON object (e.g., 969 * because account lockout is not configured in the password policy 970 * that governs the user). 971 */ 972 @Nullable() 973 public Integer getFailureLockoutCount() 974 { 975 return passwordPolicyStateObject.getFieldAsInteger( 976 FAILURE_LOCKOUT_COUNT.getFieldName()); 977 } 978 979 980 981 /** 982 * Retrieves the current number of failed authentication attempts for the 983 * user account. 984 * 985 * @return The current number of failed authentication attempts for the user 986 * account, or {@code null} if this was not included in the password 987 * policy state JSON object (e.g., because account lockout is not 988 * configured in the password policy that governs the user). 989 */ 990 @Nullable() 991 public Integer getCurrentAuthenticationFailureCount() 992 { 993 return passwordPolicyStateObject.getFieldAsInteger( 994 CURRENT_AUTHENTICATION_FAILURE_COUNT.getFieldName()); 995 } 996 997 998 999 /** 1000 * Retrieves the remaining number of failed authentication attempts required 1001 * to lock the user account. 1002 * 1003 * @return The remaining number of failed authentication attempts required to 1004 * lock the user account, or {@code null} if this was not included in 1005 * the password policy state JSON object (e.g., because account 1006 * lockout is not configured in the password policy that governs the 1007 * user). 1008 */ 1009 @Nullable() 1010 public Integer getRemainingAuthenticationFailureCount() 1011 { 1012 return passwordPolicyStateObject.getFieldAsInteger( 1013 REMAINING_AUTHENTICATION_FAILURE_COUNT.getFieldName()); 1014 } 1015 1016 1017 1018 /** 1019 * Retrieves a list of the outstanding authentication failure times for the 1020 * user account. 1021 * 1022 * @return A list of the outstanding authentication failure times for the 1023 * user account, or an empty list if there are no outstanding 1024 * authentication failures or if this was not included in the 1025 * password policy state JSON object (e.g., because account lockout 1026 * is not configured in the password policy that governs the user). 1027 */ 1028 @NotNull() 1029 public List<Date> getAuthenticationFailureTimes() 1030 { 1031 final List<Date> authFailureTimes = new ArrayList<>(); 1032 1033 final List<JSONValue> values = passwordPolicyStateObject.getFieldAsArray( 1034 AUTHENTICATION_FAILURE_TIMES.getFieldName()); 1035 if (values != null) 1036 { 1037 for (final JSONValue v : values) 1038 { 1039 try 1040 { 1041 final String valueString = ((JSONString) v).stringValue(); 1042 authFailureTimes.add(StaticUtils.decodeRFC3339Time(valueString)); 1043 } 1044 catch (final Exception e) 1045 { 1046 Debug.debugException(e); 1047 } 1048 } 1049 } 1050 1051 return Collections.unmodifiableList(authFailureTimes); 1052 } 1053 1054 1055 1056 /** 1057 * Retrieves the time that the user's account was locked as a result of too 1058 * many failed authentication attempts. 1059 * 1060 * @return The time that the user's account was locked as a result of too 1061 * many failed authentication attempts, or {@code null} if this was 1062 * not included in the password policy state JSON object (e.g., 1063 * because the user's account is not failure locked). 1064 */ 1065 @Nullable() 1066 public Date getFailureLockoutTime() 1067 { 1068 return getDate(FAILURE_LOCKOUT_TIME); 1069 } 1070 1071 1072 1073 /** 1074 * Retrieves the length of time in seconds that a user's account will be 1075 * locked after too many failed authentication attempts. 1076 * 1077 * @return The length of time in seconds that a user's account will be 1078 * locked after too many failed authentication attempts, or 1079 * {@code null} if this was not included in the password policy state 1080 * JSON object (e.g., because account lockout is not configured in 1081 * the password policy that governs the user, or because account 1082 * lockout is not temporary). 1083 */ 1084 @Nullable() 1085 public Integer getFailureLockoutDurationSeconds() 1086 { 1087 return passwordPolicyStateObject.getFieldAsInteger( 1088 FAILURE_LOCKOUT_DURATION_SECONDS.getFieldName()); 1089 1090 } 1091 1092 1093 1094 /** 1095 * Retrieves the time that the user's failure-locked account will be 1096 * automatically unlocked. 1097 * 1098 * @return The time that the user's failure-locked account will be 1099 * automatically unlocked, or {@code null} if this was not included 1100 * in the password policy state JSON object (e.g., because the user's 1101 * account is not failure locked, or because the lockout is not 1102 * temporary). 1103 */ 1104 @Nullable() 1105 public Date getFailureLockoutExpirationTime() 1106 { 1107 return getDate(FAILURE_LOCKOUT_EXPIRATION_TIME); 1108 } 1109 1110 1111 1112 /** 1113 * Retrieves the length of time in seconds remaining until the user's 1114 * failure-locked account will be automatically unlocked. 1115 * 1116 * @return The length of time in seconds remaining until the user's 1117 * failure-locked account will be automatically unlocked, or 1118 * {@code null} if this was not included in the password policy state 1119 * JSON object (e.g., because the user's account is not failure 1120 * locked, or because the lockout is not temporary). 1121 */ 1122 @Nullable() 1123 public Integer getSecondsRemainingInFailureLockout() 1124 { 1125 return passwordPolicyStateObject.getFieldAsInteger( 1126 SECONDS_REMAINING_IN_FAILURE_LOCKOUT.getFieldName()); 1127 } 1128 1129 1130 1131 /** 1132 * Retrieves the time that the user last successfully authenticated to the 1133 * server. 1134 * 1135 * @return The time that the user last successfully authenticated to the 1136 * server, or {@code null} if this was not included in the password 1137 * policy state JSON object (e.g., because last login time tracking 1138 * is not configured in the password policy that governs the user). 1139 */ 1140 @Nullable() 1141 public Date getLastLoginTime() 1142 { 1143 return getDate(LAST_LOGIN_TIME); 1144 } 1145 1146 1147 1148 /** 1149 * Retrieves the length of time in seconds since the user last successfully 1150 * authenticated to the server. 1151 * 1152 * @return The length of time in seconds since the user last successfully 1153 * authenticated to the server, or {@code null} if this was not 1154 * included in the password policy state JSON object (e.g., because 1155 * last login time tracking is not configured in the password policy 1156 * that governs the user). 1157 */ 1158 @Nullable() 1159 public Integer getSecondsSinceLastLogin() 1160 { 1161 return passwordPolicyStateObject.getFieldAsInteger( 1162 SECONDS_SINCE_LAST_LOGIN.getFieldName()); 1163 } 1164 1165 1166 1167 /** 1168 * Retrieves the IP address of the client from which the user last 1169 * successfully authenticated. 1170 * 1171 * @return The IP address of the client from which the user last successfully 1172 * authenticated, or {@code null} if this was not included in the 1173 * password policy state JSON object (e.g., because last login IP 1174 * address tracking is not configured in the password policy that 1175 * governs the user). 1176 */ 1177 @Nullable() 1178 public String getLastLoginIPAddress() 1179 { 1180 return passwordPolicyStateObject.getFieldAsString( 1181 LAST_LOGIN_IP_ADDRESS.getFieldName()); 1182 } 1183 1184 1185 1186 /** 1187 * Retrieves the value of a flag that indicates whether the user's account is 1188 * currently locked because it has been too long since they last authenticated 1189 * to the server. 1190 * 1191 * @return {@code Boolean.TRUE} if the user's account is currently 1192 * idle-locked, {@code Boolean.FALSE} if the user's account is not 1193 * currently idle-locked, or {@code null} if this flag was not 1194 * included in the password policy state JSON object. 1195 */ 1196 @Nullable() 1197 public Boolean getAccountIsIdleLocked() 1198 { 1199 return passwordPolicyStateObject.getFieldAsBoolean( 1200 ACCOUNT_IS_IDLE_LOCKED.getFieldName()); 1201 } 1202 1203 1204 1205 /** 1206 * Retrieves the maximum length of time in seconds that can elapse between 1207 * successful authentications before the user's account is locked. 1208 * 1209 * @return The maximum length of time in seconds that can elapse between 1210 * successful authentications before the user's account is locked, or 1211 * {@code null} if this was not included in the password policy state 1212 * JSON object (e.g., because idle lockout is not configured in the 1213 * password policy that governs the user). 1214 */ 1215 @Nullable() 1216 public Integer getIdleLockoutIntervalSeconds() 1217 { 1218 return passwordPolicyStateObject.getFieldAsInteger( 1219 IDLE_LOCKOUT_INTERVAL_SECONDS.getFieldName()); 1220 } 1221 1222 1223 1224 /** 1225 * Retrieves the time that the user's account will be (or was) locked for 1226 * allowing too much time to elapse between successful authentications. 1227 * 1228 * @return The time that the user's account will be (or was) locked for 1229 * allowing too much time to elapse between successful 1230 * authentications, or {@code null} if this was not included in the 1231 * password policy state JSON object (e.g., because idle lockout is 1232 * not configured in the password policy that governs the user). 1233 */ 1234 @Nullable() 1235 public Date getIdleLockoutTime() 1236 { 1237 return getDate(IDLE_LOCKOUT_TIME); 1238 } 1239 1240 1241 1242 /** 1243 * Retrieves the length of time in seconds until the user's account will be 1244 * locked for allowing too much time to elapse between successful 1245 * authentications. 1246 * 1247 * @return The length of time in seconds until the user's account will be 1248 * locked for allowing too much time to elapse between successful 1249 * authentication, or {@code null} if this was not included in the 1250 * password policy state JSON object (e.g., because idle lockout is 1251 * not configured in the password policy that governs the user, or 1252 * because the user's account is already idle-locked). 1253 */ 1254 @Nullable() 1255 public Integer getSecondsUntilIdleLockout() 1256 { 1257 return passwordPolicyStateObject.getFieldAsInteger( 1258 SECONDS_UNTIL_IDLE_LOCKOUT.getFieldName()); 1259 } 1260 1261 1262 1263 /** 1264 * Retrieves the length of time in seconds since the user's account was 1265 * locked for allowing too much time to elapse between successful 1266 * authentications. 1267 * 1268 * @return The length of time in seconds since the user's account was locked 1269 * for allowing too much time to elapse between successful 1270 * authentication, or {@code null} if this was not included in the 1271 * password policy state JSON object (e.g., because idle lockout is 1272 * not configured in the password policy that governs the user, or 1273 * because the user's account is not idle-locked). 1274 */ 1275 @Nullable() 1276 public Integer getSecondsSinceIdleLockout() 1277 { 1278 return passwordPolicyStateObject.getFieldAsInteger( 1279 SECONDS_SINCE_IDLE_LOCKOUT.getFieldName()); 1280 } 1281 1282 1283 1284 /** 1285 * Retrieves the value of a flag that indicates whether the user must change 1286 * their password before they will be allowed to perform any other operations 1287 * in the server. 1288 * 1289 * @return {@code Boolean.TRUE} if the user must change their password before 1290 * they will be allowed to perform any other operations in the 1291 * server, {@code Boolean.FALSE} if the user is not required to 1292 * change their password, or {@code null} if this flag was not 1293 * included in the password policy state JSON object. 1294 */ 1295 @Nullable() 1296 public Boolean getMustChangePassword() 1297 { 1298 return passwordPolicyStateObject.getFieldAsBoolean( 1299 MUST_CHANGE_PASSWORD.getFieldName()); 1300 } 1301 1302 1303 1304 /** 1305 * Retrieves the value of a flag that indicates whether the user's account is 1306 * locked because they failed to choose a new password in a timely manner 1307 * after an administrative reset. 1308 * 1309 * @return {@code Boolean.TRUE} if the user's account is currently 1310 * reset-locked, {@code Boolean.FALSE} if the user's account is not 1311 * reset-locked, or {@code null} if this flag was not included in the 1312 * password policy state JSON object. 1313 */ 1314 @Nullable() 1315 public Boolean getAccountIsResetLocked() 1316 { 1317 return passwordPolicyStateObject.getFieldAsBoolean( 1318 ACCOUNT_IS_RESET_LOCKED.getFieldName()); 1319 } 1320 1321 1322 1323 /** 1324 * Retrieves the value of a flag that indicates whether the password policy 1325 * that governs the user is configured to require users to choose a new 1326 * password the first time they authenticate after their account is created. 1327 * 1328 * @return {@code Boolean.TRUE} if users are required to choose a new 1329 * password the first time they authenticate after their account is 1330 * created, {@code Boolean.FALSE} if users are not required to choose 1331 * a new password after their account is created, or {@code null} if 1332 * this flag was not included in the password policy state JSON 1333 * object. 1334 */ 1335 @Nullable() 1336 public Boolean getForceChangeOnAdd() 1337 { 1338 return passwordPolicyStateObject.getFieldAsBoolean( 1339 FORCE_CHANGE_ON_ADD.getFieldName()); 1340 } 1341 1342 1343 1344 /** 1345 * Retrieves the value of a flag that indicates whether the password policy 1346 * that governs the user is configured to require users to choose a new 1347 * password the first time they authenticate after their password has been 1348 * reset by an administrator. 1349 * 1350 * @return {@code Boolean.TRUE} if users are required to choose a new 1351 * password the first time they authenticate after their password is 1352 * reset, {@code Boolean.FALSE} if users are not required to choose 1353 * a new password after their password is reset, or {@code null} if 1354 * this flag was not included in the password policy state JSON 1355 * object. 1356 */ 1357 @Nullable() 1358 public Boolean getForceChangeOnReset() 1359 { 1360 return passwordPolicyStateObject.getFieldAsBoolean( 1361 FORCE_CHANGE_ON_RESET.getFieldName()); 1362 } 1363 1364 1365 1366 /** 1367 * Retrieves the maximum length of time in seconds that a user has to change 1368 * their password after an administrative reset before their account will be 1369 * locked. 1370 * 1371 * @return The maximum length of time in seconds that a user has to change 1372 * their password after an administrative reset before their account 1373 * will be locked, or {@code null} if this was not included in the 1374 * password policy state JSON object (e.g., because reset lockout is 1375 * not configured in the password policy that governs the user). 1376 */ 1377 @Nullable() 1378 public Integer getMaximumPasswordResetAgeSeconds() 1379 { 1380 return passwordPolicyStateObject.getFieldAsInteger( 1381 MAXIMUM_PASSWORD_RESET_AGE_SECONDS.getFieldName()); 1382 } 1383 1384 1385 1386 /** 1387 * Retrieves the time that the user's account will be (or was) locked after 1388 * failing to choose a new password in a timely manner after an administrative 1389 * reset. 1390 * 1391 * @return The time that the user's account will be (or wa) locked after 1392 * failing to choose a new password in a timely manner after an 1393 * administrative reset, or {@code null} if this was not included in 1394 * the password policy state JSON object (e.g., because reset lockout 1395 * is not configured in the password policy that governs the user, 1396 * or because the user's password has not been reset). 1397 */ 1398 @Nullable() 1399 public Date getResetLockoutTime() 1400 { 1401 return getDate(RESET_LOCKOUT_TIME); 1402 } 1403 1404 1405 1406 /** 1407 * Retrieves the length of time in seconds until the user's account will be 1408 * locked for failing to choose a new password after an administrative 1409 * reset. 1410 * 1411 * @return The length of time in seconds until the user's account will be 1412 * locked for failing to choose a new password after an 1413 * administrative reset, or {@code null} if this was not included in 1414 * the password policy state JSON object (e.g., because reset lockout 1415 * is not configured in the password policy that governs the user, 1416 * because the user's password has not been reset, or because the 1417 * user's account is already reset-locked). 1418 */ 1419 @Nullable() 1420 public Integer getSecondsUntilResetLockout() 1421 { 1422 return passwordPolicyStateObject.getFieldAsInteger( 1423 SECONDS_UNTIL_RESET_LOCKOUT.getFieldName()); 1424 } 1425 1426 1427 1428 /** 1429 * Retrieves the maximum number of passwords that the server will maintain in 1430 * the user's password history. 1431 * 1432 * @return The maximum number of passwords that the server will maintain in 1433 * the user's password history, or {@code null} if this was not 1434 * included in the password policy state JSON object (e.g., because 1435 * the password policy that governs the user is not configured to 1436 * maintain a password history, or because it maintains a password 1437 * history based on a duration rather than a count). 1438 */ 1439 @Nullable() 1440 public Integer getMaximumPasswordHistoryCount() 1441 { 1442 return passwordPolicyStateObject.getFieldAsInteger( 1443 MAXIMUM_PASSWORD_HISTORY_COUNT.getFieldName()); 1444 } 1445 1446 1447 1448 /** 1449 * Retrieves the maximum length of time in seconds that the server will 1450 * maintain passwords in the user's password history. 1451 * 1452 * @return The maximum length of time in seconds that the server will 1453 * maintain passwords in the user's password history, or 1454 * {@code null} if this was not included in the password policy 1455 * state JSON object (e.g., because the password policy that governs 1456 * the user is not configured to maintain a password history, or 1457 * because it maintains a password history based on a count rather 1458 * than a duration). 1459 */ 1460 @Nullable() 1461 public Integer getMaximumPasswordHistoryDurationSeconds() 1462 { 1463 return passwordPolicyStateObject.getFieldAsInteger( 1464 MAXIMUM_PASSWORD_HISTORY_DURATION_SECONDS.getFieldName()); 1465 } 1466 1467 1468 1469 /** 1470 * Retrieves the number of passwords currently held in the user's password 1471 * history. 1472 * 1473 * @return The number of passwords currently held in the user's password 1474 * history, or {@code null} if this was not incldued in the password 1475 * policy state JSON object (e.g., because the password policy that 1476 * governs the user is not configured to maintain a password 1477 * history). 1478 */ 1479 @Nullable() 1480 public Integer getCurrentPasswordHistoryCount() 1481 { 1482 return passwordPolicyStateObject.getFieldAsInteger( 1483 CURRENT_PASSWORD_HISTORY_COUNT.getFieldName()); 1484 } 1485 1486 1487 1488 /** 1489 * Indicates whether the user is currently prohibited from changing their 1490 * password because not enough time has elapsed since they last changed their 1491 * password. 1492 * 1493 * @return {@code Boolean.TRUE} if the user is currently prohibited from 1494 * changing their password because not enough time has elapsed since 1495 * they last changed their password, {@code Boolean.FALSE} if the 1496 * user is not prohibited from changing their password because of the 1497 * minimum password age, or {@code null} if this flag was not 1498 * included in the password policy state JSON object. 1499 */ 1500 @Nullable() 1501 public Boolean getIsWithinMinimumPasswordAge() 1502 { 1503 return passwordPolicyStateObject.getFieldAsBoolean( 1504 IS_WITHIN_MINIMUM_PASSWORD_AGE.getFieldName()); 1505 } 1506 1507 1508 1509 /** 1510 * Retrieves the minimum length of time in seconds that must elapse after a 1511 * user changes their password before they will be permitted to change it 1512 * again. 1513 * 1514 * @return The minimum length of time in seconds that must elapse after a 1515 * user changes their password before they will be permitted to 1516 * change it again, or {@code null} if this was not included in the 1517 * password policy state JSON object (e.g., because no minimum 1518 * password age is configured in the password policy that governs the 1519 * user). 1520 */ 1521 @Nullable() 1522 public Integer getMinimumPasswordAgeSeconds() 1523 { 1524 return passwordPolicyStateObject.getFieldAsInteger( 1525 MINIMUM_PASSWORD_AGE_SECONDS.getFieldName()); 1526 } 1527 1528 1529 1530 /** 1531 * Retrieves the earliest time that the user will be permitted to change their 1532 * password as a result of the minimum password age. 1533 * 1534 * @return The earliest time that the user will be permitted to change their 1535 * password as a result of the minimum password age, or {@code null} 1536 * if this was not included in the password policy state JSON 1537 * object (e.g., because no minimum password age is configured in the 1538 * password policy that governs the user, or because it has been 1539 * longer than the minimum age since they last changed their 1540 * password). 1541 */ 1542 @Nullable() 1543 public Date getMinimumPasswordAgeExpirationTime() 1544 { 1545 return getDate(MINIMUM_PASSWORD_AGE_EXPIRATION_TIME); 1546 } 1547 1548 1549 1550 /** 1551 * Retrieves the length of time in seconds remaining until the user will be 1552 * permitted to change their password as a result of the minimum password age. 1553 * 1554 * @return The length of time in seconds remaining until the user will be 1555 * permitted to change their password as a result of the minimum 1556 * password age, or {@code null} if this was not included in the 1557 * password policy state JSON object (e.g., because no minimum 1558 * password age is configured in the password policy that governs the 1559 * user, or because it has been longer than the minimum age since 1560 * they last changed their password). 1561 */ 1562 @Nullable() 1563 public Integer getSecondsRemainingInMinimumPasswordAge() 1564 { 1565 return passwordPolicyStateObject.getFieldAsInteger( 1566 SECONDS_REMAINING_IN_MINIMUM_PASSWORD_AGE.getFieldName()); 1567 } 1568 1569 1570 1571 /** 1572 * Retrieves the maximum number of grace login attempts that the user will 1573 * have to allow them to change an expired password. 1574 * 1575 * @return The maximum number of grace login attempts that the user will have 1576 * to allow them to change an expired password, or {@code null} if 1577 * this was not included in the password policy state JSON object 1578 * (e.g., if grace logins are not configured in the password policy 1579 * that governs the user). 1580 */ 1581 @Nullable() 1582 public Integer getMaximumGraceLoginCount() 1583 { 1584 return passwordPolicyStateObject.getFieldAsInteger( 1585 MAXIMUM_GRACE_LOGIN_COUNT.getFieldName()); 1586 } 1587 1588 1589 1590 /** 1591 * Retrieves the number of grace logins that the user has currently used. 1592 * 1593 * @return The number of grace login attempts that the user has currently 1594 * used, or {@code null} if this was not included in the password 1595 * policy state JSON object (e.g., if grace logins are not configured 1596 * in the password policy that governs the user). 1597 */ 1598 @Nullable() 1599 public Integer getUsedGraceLoginCount() 1600 { 1601 return passwordPolicyStateObject.getFieldAsInteger( 1602 USED_GRACE_LOGIN_COUNT.getFieldName()); 1603 } 1604 1605 1606 1607 /** 1608 * Retrieves the remaining number of grace logins for the user. 1609 * 1610 * @return The remaining number of grace logins for the user, or {@code null} 1611 * if this was not included in the password policy state JSON object 1612 * (e.g., if grace logins are not configured in the password policy 1613 * that governs the user). 1614 */ 1615 @Nullable() 1616 public Integer getRemainingGraceLoginCount() 1617 { 1618 return passwordPolicyStateObject.getFieldAsInteger( 1619 REMAINING_GRACE_LOGIN_COUNT.getFieldName()); 1620 } 1621 1622 1623 1624 /** 1625 * Retrieves a list of the times that the user has used a grace login to 1626 * authenticate. 1627 * 1628 * @return A list of the times that the user has used a grace login to 1629 * authenticate, or an empty list if the user has not used any grace 1630 * logins, or if this was not included in the password policy state 1631 * JSON object (e.g., if grace logins are not configured in the 1632 * password policy that governs the user). 1633 */ 1634 @NotNull() 1635 public List<Date> getGraceLoginUseTimes() 1636 { 1637 final List<Date> graceLoginTimes = new ArrayList<>(); 1638 1639 final List<JSONValue> values = passwordPolicyStateObject.getFieldAsArray( 1640 GRACE_LOGIN_USE_TIMES.getFieldName()); 1641 if (values != null) 1642 { 1643 for (final JSONValue v : values) 1644 { 1645 try 1646 { 1647 final String valueString = ((JSONString) v).stringValue(); 1648 graceLoginTimes.add(StaticUtils.decodeRFC3339Time(valueString)); 1649 } 1650 catch (final Exception e) 1651 { 1652 Debug.debugException(e); 1653 } 1654 } 1655 } 1656 1657 return Collections.unmodifiableList(graceLoginTimes); 1658 } 1659 1660 1661 1662 /** 1663 * Retrieves the value of a flag that indicates whether the user account has a 1664 * retired former password that may still be used to authenticate. 1665 * 1666 * @return {@code Boolean.TRUE} if the user account currently has a valid 1667 * retired password, {@code Boolean.FALSE} if the user account does 1668 * not have a valid retired password, or {@code null} if this flag 1669 * was not included in the password policy state JSON object. 1670 */ 1671 @Nullable() 1672 public Boolean getHasRetiredPassword() 1673 { 1674 return passwordPolicyStateObject.getFieldAsBoolean( 1675 HAS_RETIRED_PASSWORD.getFieldName()); 1676 } 1677 1678 1679 1680 /** 1681 * Retrieves the time that the user's retired password will expire and can no 1682 * longer be used to authenticate. 1683 * 1684 * @return The time that the user's retired password will expire, or 1685 * {@code null} if this was not included in the password policy state 1686 * JSON object (e.g., because the user does not have a retired 1687 * password). 1688 */ 1689 @Nullable() 1690 public Date getRetiredPasswordExpirationTime() 1691 { 1692 return getDate(RETIRED_PASSWORD_EXPIRATION_TIME); 1693 } 1694 1695 1696 1697 /** 1698 * Retrieves the length of time in seconds remaining until the user's retired 1699 * password expires and can no longer be used to authenticate. 1700 * 1701 * @return The length of time in seconds remaining until the user's retired 1702 * password expires, or {@code null} if this was not included in the 1703 * password policy state JSON object (e.g., because the user does not 1704 * have a retired password). 1705 */ 1706 @Nullable() 1707 public Integer getSecondsUntilRetiredPasswordExpiration() 1708 { 1709 return passwordPolicyStateObject.getFieldAsInteger( 1710 SECONDS_UNTIL_RETIRED_PASSWORD_EXPIRATION.getFieldName()); 1711 } 1712 1713 1714 1715 /** 1716 * Retrieves the value of a flag that indicates whether the user will be 1717 * required to authenticate in a secure manner that does not reveal their 1718 * credentials to an observer. 1719 * 1720 * @return {@code Boolean.TRUE} if the user will be required to authenticate 1721 * in a secure manner, {@code Boolean.FALSE} if the user will not be 1722 * required to authenticate in a secure manner, or {@code null} if 1723 * this flag was not included in the password policy state JSON 1724 * object. 1725 */ 1726 @Nullable() 1727 public Boolean getRequireSecureAuthentication() 1728 { 1729 return passwordPolicyStateObject.getFieldAsBoolean( 1730 REQUIRE_SECURE_AUTHENTICATION.getFieldName()); 1731 } 1732 1733 1734 1735 /** 1736 * Retrieves the value of a flag that indicates whether the user will be 1737 * required to change their password in a secure manner that does not reveal 1738 * their credentials to an observer. 1739 * 1740 * @return {@code Boolean.TRUE} if the user will be required to change their 1741 * password in a secure manner, {@code Boolean.FALSE} if the user 1742 * will not be required to change their password in a secure manner, 1743 * or {@code null} if this flag was not included in the password 1744 * policy state JSON object. 1745 */ 1746 @Nullable() 1747 public Boolean getRequireSecurePasswordChanges() 1748 { 1749 return passwordPolicyStateObject.getFieldAsBoolean( 1750 REQUIRE_SECURE_PASSWORD_CHANGES.getFieldName()); 1751 } 1752 1753 1754 1755 /** 1756 * Retrieves a list of the names of the SASL mechanisms that the user can use 1757 * to authenticate. 1758 * 1759 * @return A list of the names of the SASL mechanisms that the user can use 1760 * to authenticate, or an empty list if no SASL mechanisms are 1761 * available to the user or if this was not included in the password 1762 * policy state JSON object. 1763 */ 1764 @NotNull() 1765 public List<String> getAvailableSASLMechanisms() 1766 { 1767 final List<String> saslMechanismNames = new ArrayList<>(); 1768 1769 final List<JSONValue> values = passwordPolicyStateObject.getFieldAsArray( 1770 AVAILABLE_SASL_MECHANISMS.getFieldName()); 1771 if (values != null) 1772 { 1773 for (final JSONValue v : values) 1774 { 1775 try 1776 { 1777 saslMechanismNames.add(((JSONString) v).stringValue()); 1778 } 1779 catch (final Exception e) 1780 { 1781 Debug.debugException(e); 1782 } 1783 } 1784 } 1785 1786 return Collections.unmodifiableList(saslMechanismNames); 1787 } 1788 1789 1790 1791 /** 1792 * Retrieves a list of the names of the OTP delivery mechanisms that the user 1793 * can use to receive one-time passwords, password reset tokens, and 1794 * single-use tokens. 1795 * 1796 * @return A list of the names of the OTP delivery mechanisms that the user 1797 * can use, or an empty list if no OTP delivery mechanisms are 1798 * available to the user or if this was not included in the password 1799 * policy state JSON object. 1800 */ 1801 @NotNull() 1802 public List<String> getAvailableOTPDeliveryMechanisms() 1803 { 1804 final List<String> deliveryMechanismNames = new ArrayList<>(); 1805 1806 final List<JSONValue> values = passwordPolicyStateObject.getFieldAsArray( 1807 AVAILABLE_OTP_DELIVERY_MECHANISMS.getFieldName()); 1808 if (values != null) 1809 { 1810 for (final JSONValue v : values) 1811 { 1812 try 1813 { 1814 deliveryMechanismNames.add(((JSONString) v).stringValue()); 1815 } 1816 catch (final Exception e) 1817 { 1818 Debug.debugException(e); 1819 } 1820 } 1821 } 1822 1823 return Collections.unmodifiableList(deliveryMechanismNames); 1824 } 1825 1826 1827 1828 /** 1829 * Retrieves the value of a flag that indicates whether the user account has 1830 * at least one TOTP shared secret that can be used to authenticate with 1831 * time-based one-time passwords via the UNBOUNDID-TOTP SASL mechanism. 1832 * 1833 * @return {@code Boolean.TRUE} if the user account has at least one TOTP 1834 * shared secret, {@code Boolean.FALSE} if the user account does not 1835 * have any TOTP shared secrets, or {@code null} if this flag was not 1836 * included in the password policy state JSON object. 1837 */ 1838 @Nullable() 1839 public Boolean getHasTOTPSharedSecret() 1840 { 1841 return passwordPolicyStateObject.getFieldAsBoolean( 1842 HAS_TOTP_SHARED_SECRET.getFieldName()); 1843 } 1844 1845 1846 1847 /** 1848 * Retrieves the value of a flag that indicates whether the user account has 1849 * at least one registered YubiKey OTP device that can be used to authenticate 1850 * via the UNBOUNDID-YUBIKEY-OTP SASL mechanism. 1851 * 1852 * @return {@code Boolean.TRUE} if the user account has at least one 1853 * registered YubiKey OTP device, {@code Boolean.FALSE} if the user 1854 * account does not have any registered YubiKey OTP devices, or 1855 * {@code null} if this flag was not included in the password policy 1856 * state JSON object. 1857 */ 1858 @Nullable() 1859 public Boolean getHasRegisteredYubiKeyOTPDevice() 1860 { 1861 return passwordPolicyStateObject.getFieldAsBoolean( 1862 HAS_REGISTERED_YUBIKEY_OTP_DEVICE.getFieldName()); 1863 } 1864 1865 1866 1867 /** 1868 * Retrieves the value of a flag that indicates whether the user account is 1869 * currently locked because it contains a password that does not satisfy all 1870 * of the configured password validators. 1871 * 1872 * @return {@code Boolean.TRUE} if the user account is locked because it 1873 * contains a password that does not satisfy all of the configured 1874 * password validators, {@code Boolean.FALSE} if the account is not 1875 * validation-locked, or {@code null} if this flag was not included 1876 * in the password policy state JSON object. 1877 */ 1878 @Nullable() 1879 public Boolean getAccountIsValidationLocked() 1880 { 1881 return passwordPolicyStateObject.getFieldAsBoolean( 1882 ACCOUNT_IS_VALIDATION_LOCKED.getFieldName()); 1883 } 1884 1885 1886 1887 /** 1888 * Retrieves the time that the server last invoked password validators during 1889 * a bind operation for the user. 1890 * 1891 * @return The time that the server last invoked password validators during a 1892 * bind operation for the user, or {@code null} if this was not 1893 * included in the password policy state JSON object. 1894 */ 1895 @Nullable() 1896 public Date getLastBindPasswordValidationTime() 1897 { 1898 return getDate(LAST_BIND_PASSWORD_VALIDATION_TIME); 1899 } 1900 1901 1902 1903 /** 1904 * Retrieves the length of time in seconds that has passed since the server 1905 * last invoked password validators during a bind operation for the user. 1906 * 1907 * @return The length of time in seconds that has passed since the server 1908 * last invoked password validators during a bind operation for the 1909 * user, or {@code null} if this was not included in the password 1910 * policy state JSON object. 1911 */ 1912 @Nullable() 1913 public Integer getSecondsSinceLastBindPasswordValidation() 1914 { 1915 return passwordPolicyStateObject.getFieldAsInteger( 1916 SECONDS_SINCE_LAST_BIND_PASSWORD_VALIDATION.getFieldName()); 1917 } 1918 1919 1920 1921 /** 1922 * Retrieves the minimum length of time in seconds that should pass between 1923 * invocations of password validators during a bind operation for the user. 1924 * 1925 * @return The minimum length of time in seconds that should pass between 1926 * invocations of password validators during a bind operation for 1927 * each user, or {@code null} if this was not included in the 1928 * password policy state JSON object. 1929 */ 1930 @Nullable() 1931 public Integer getMinimumBindPasswordValidationFrequencySeconds() 1932 { 1933 return passwordPolicyStateObject.getFieldAsInteger( 1934 MINIMUM_BIND_PASSWORD_VALIDATION_FREQUENCY_SECONDS.getFieldName()); 1935 } 1936 1937 1938 1939 /** 1940 * Retrieves the name of the action that the server should take if the 1941 * password provided during a bind operation fails to satisfy one or more 1942 * password validators. 1943 * 1944 * @return The name of the action that the server should take if the password 1945 * provided during a bind operation fails to satisfy one or more 1946 * password validators, or {@code null} if this was not included in 1947 * the password policy state JSON object. 1948 */ 1949 @Nullable() 1950 public String getBindPasswordValidationFailureAction() 1951 { 1952 return passwordPolicyStateObject.getFieldAsString( 1953 BIND_PASSWORD_VALIDATION_FAILURE_ACTION.getFieldName()); 1954 } 1955 1956 1957 1958 /** 1959 * Retrieves the recent login history for the user. 1960 * 1961 * @return The recent login history for the user, or {@code null} if this was 1962 * not included in the password policy state JSON object. 1963 * 1964 * @throws LDAPException If a problem occurs while trying to parse the 1965 * recent login history for the user. 1966 */ 1967 @Nullable() 1968 public RecentLoginHistory getRecentLoginHistory() 1969 throws LDAPException 1970 { 1971 final JSONObject o = passwordPolicyStateObject.getFieldAsObject( 1972 RECENT_LOGIN_HISTORY.getFieldName()); 1973 if (o == null) 1974 { 1975 return null; 1976 } 1977 else 1978 { 1979 return new RecentLoginHistory(o); 1980 } 1981 } 1982 1983 1984 1985 /** 1986 * Retrieves the maximum number of recent successful login attempts the server 1987 * should maintain for a user. 1988 * 1989 * @return The maximum number of recent successful login attempts the server 1990 * should maintain for a user, or {@code null}if this was not 1991 * included in the password policy state JSON object. 1992 */ 1993 @Nullable() 1994 public Integer getMaximumRecentLoginHistorySuccessfulAuthenticationCount() 1995 { 1996 return passwordPolicyStateObject.getFieldAsInteger( 1997 MAXIMUM_RECENT_LOGIN_HISTORY_SUCCESSFUL_AUTHENTICATION_COUNT. 1998 getFieldName()); 1999 } 2000 2001 2002 2003 /** 2004 * Retrieves the maximum age in seconds of recent successful login attempts 2005 * the server should maintain for a user. 2006 * 2007 * @return The maximum age in seconds of recent successful login attempts the 2008 * server should maintain for a user, or {@code null}if this was not 2009 * included in the password policy state JSON object. 2010 */ 2011 @Nullable() 2012 public Integer 2013 getMaximumRecentLoginHistorySuccessfulAuthenticationDurationSeconds() 2014 { 2015 return passwordPolicyStateObject.getFieldAsInteger( 2016 MAXIMUM_RECENT_LOGIN_HISTORY_SUCCESSFUL_AUTHENTICATION_DURATION_SECONDS 2017 .getFieldName()); 2018 } 2019 2020 2021 2022 /** 2023 * Retrieves the maximum number of recent failed login attempts the server 2024 * should maintain for a user. 2025 * 2026 * @return The maximum number of recent failed login attempts the server 2027 * should maintain for a user, or {@code null}if this was not 2028 * included in the password policy state JSON object. 2029 */ 2030 @Nullable() 2031 public Integer getMaximumRecentLoginHistoryFailedAuthenticationCount() 2032 { 2033 return passwordPolicyStateObject.getFieldAsInteger( 2034 MAXIMUM_RECENT_LOGIN_HISTORY_FAILED_AUTHENTICATION_COUNT. 2035 getFieldName()); 2036 } 2037 2038 2039 2040 /** 2041 * Retrieves the maximum age in seconds of recent failed login attempts 2042 * the server should maintain for a user. 2043 * 2044 * @return The maximum age in seconds of recent failed login attempts the 2045 * server should maintain for a user, or {@code null}if this was not 2046 * included in the password policy state JSON object. 2047 */ 2048 @Nullable() 2049 public Integer 2050 getMaximumRecentLoginHistoryFailedAuthenticationDurationSeconds() 2051 { 2052 return passwordPolicyStateObject.getFieldAsInteger( 2053 MAXIMUM_RECENT_LOGIN_HISTORY_FAILED_AUTHENTICATION_DURATION_SECONDS. 2054 getFieldName()); 2055 } 2056 2057 2058 2059 /** 2060 * Retrieves the list of quality requirements that must be satisfied for 2061 * passwords included in new entries that are added using the same password 2062 * policy as the associated entry. 2063 * 2064 * @return The list of password quality requirements that will be enforced 2065 * for adds using the same password policy as the associated entry, 2066 * or an empty list if no requirements will be imposed. 2067 */ 2068 @NotNull() 2069 public List<PasswordQualityRequirement> getAddPasswordQualityRequirements() 2070 { 2071 return getPasswordQualityRequirements(REQUIREMENT_FIELD_APPLIES_TO_ADD); 2072 } 2073 2074 2075 2076 /** 2077 * Retrieves the list of quality requirements that must be satisfied when the 2078 * associated user attempts to change their own password. 2079 * 2080 * @return The list of password quality requirements that will be enforced 2081 * for self password changes, or an empty list if no requirements 2082 * will be imposed. 2083 */ 2084 @NotNull() 2085 public List<PasswordQualityRequirement> 2086 getSelfChangePasswordQualityRequirements() 2087 { 2088 return getPasswordQualityRequirements( 2089 REQUIREMENT_FIELD_APPLIES_TO_SELF_CHANGE); 2090 } 2091 2092 2093 2094 /** 2095 * Retrieves the list of quality requirements that must be satisfied when an 2096 * administrator attempts to change the user's password. 2097 * 2098 * @return The list of password quality requirements that will be enforced 2099 * for administrative password resets, or an empty list if no 2100 * requirements will be imposed. 2101 */ 2102 @NotNull() 2103 public List<PasswordQualityRequirement> 2104 getAdministrativeResetPasswordQualityRequirements() 2105 { 2106 return getPasswordQualityRequirements( 2107 REQUIREMENT_FIELD_APPLIES_TO_ADMIN_RESET); 2108 } 2109 2110 2111 2112 /** 2113 * Retrieves the list of quality requirements that must be satisfied when the 2114 * associated user authenticates in a manner that makes the clear-text 2115 * password available to the server. 2116 * 2117 * @return The list of password quality requirements that will be enforced 2118 * for binds, or an empty list if no requirements will be imposed. 2119 */ 2120 @NotNull() 2121 public List<PasswordQualityRequirement> getBindPasswordQualityRequirements() 2122 { 2123 return getPasswordQualityRequirements(REQUIREMENT_FIELD_APPLIES_TO_BIND); 2124 } 2125 2126 2127 2128 /** 2129 * Retrieves a list of the password quality requirements that are contained in 2130 * the JSON object in which the indicated Boolean field is present and set to 2131 * {@code true}. 2132 * 2133 * @param booleanFieldName The name of the field that is expected to be 2134 * present with a Boolean value of true for each 2135 * requirement to be included in the list that is 2136 * returned. 2137 * 2138 * @return The appropriate list of password quality requirements, or an empty 2139 * list if no requirements will be imposed. 2140 */ 2141 @NotNull() 2142 private List<PasswordQualityRequirement> getPasswordQualityRequirements( 2143 @NotNull final String booleanFieldName) 2144 { 2145 final List<JSONValue> requirementObjectLst = 2146 passwordPolicyStateObject.getFieldAsArray( 2147 PASSWORD_QUALITY_REQUIREMENTS.getFieldName()); 2148 if ((requirementObjectLst == null) || requirementObjectLst.isEmpty()) 2149 { 2150 return Collections.emptyList(); 2151 } 2152 2153 final List<PasswordQualityRequirement> requirements = 2154 new ArrayList<>(requirementObjectLst.size()); 2155 for (final JSONValue requirementObjectValue : requirementObjectLst) 2156 { 2157 if (! (requirementObjectValue instanceof JSONObject)) 2158 { 2159 continue; 2160 } 2161 2162 final JSONObject requirementObject = (JSONObject) requirementObjectValue; 2163 final Boolean include = requirementObject.getFieldAsBoolean( 2164 booleanFieldName); 2165 if ((include == null) || (! include.booleanValue())) 2166 { 2167 continue; 2168 } 2169 2170 final String description = 2171 requirementObject.getFieldAsString(REQUIREMENT_FIELD_DESCRIPTION); 2172 if (description == null) 2173 { 2174 continue; 2175 } 2176 2177 final String clientSideValidationType = 2178 requirementObject.getFieldAsString( 2179 REQUIREMENT_FIELD_CLIENT_SIDE_VALIDATION_TYPE); 2180 2181 final Map<String,String> clientSideValidationProperties = 2182 new LinkedHashMap<>(); 2183 final List<JSONValue> propertyValues = requirementObject.getFieldAsArray( 2184 REQUIREMENT_FIELD_CLIENT_SIDE_VALIDATION_PROPERTIES); 2185 if (propertyValues != null) 2186 { 2187 for (final JSONValue propertyValue : propertyValues) 2188 { 2189 if (! (propertyValue instanceof JSONObject)) 2190 { 2191 continue; 2192 } 2193 2194 final JSONObject propertyObject = (JSONObject) propertyValue; 2195 final String name = propertyObject.getFieldAsString( 2196 REQUIREMENT_FIELD_CLIENT_SIDE_VALIDATION_PROPERTY_NAME); 2197 final String value = propertyObject.getFieldAsString( 2198 REQUIREMENT_FIELD_CLIENT_SIDE_VALIDATION_PROPERTY_VALUE); 2199 if ((name != null) && (value != null)) 2200 { 2201 clientSideValidationProperties.put(name, value); 2202 } 2203 } 2204 } 2205 2206 requirements.add(new PasswordQualityRequirement(description, 2207 clientSideValidationType, clientSideValidationProperties)); 2208 } 2209 2210 return requirements; 2211 } 2212 2213 2214 2215 /** 2216 * Indicates whether the user has a static password that is encoded with 2217 * settings that don't match the current configuration for the associated 2218 * password storage scheme. 2219 * 2220 * @return {@code Boolean.TRUE} if the account has a static password that 2221 * is encoded with non-current settings, {@code Boolean.FALSE} if the 2222 * account does not have a static password that is encoded with 2223 * non-current settings, or {@code null} if this flag was not 2224 * included in the password policy state JSON object. 2225 */ 2226 @Nullable() 2227 public Boolean hasPasswordEncodedWithNonCurrentSettings() 2228 { 2229 return passwordPolicyStateObject.getFieldAsBoolean( 2230 HAS_PASSWORD_ENCODED_WITH_NON_CURRENT_SETTINGS.getFieldName()); 2231 } 2232 2233 2234 2235 /** 2236 * Retrieves a map with information about the reasons that a password may not 2237 * be encoded with the current settings for the associated password storage 2238 * scheme. The keys of the map will the name of the storage scheme, and the 2239 * values will be a possibly-empty list of explanations that describe why a 2240 * password encoded with that scheme is encoded with non-current settings. 2241 * 2242 * @return A map with information about the reasons that a password may not 2243 * be encoded with the current settings for the associated password 2244 * storage scheme, or an empty map if this was not included in the 2245 * password policy state JSON object. 2246 */ 2247 @NotNull() 2248 public Map<String,List<String>> 2249 getNonCurrentPasswordStorageSchemeSettingsExplanations() 2250 { 2251 final Map<String,List<String>> explanationsMap = new LinkedHashMap<>(); 2252 2253 final List<JSONValue> values = passwordPolicyStateObject.getFieldAsArray( 2254 NON_CURRENT_PASSWORD_STORAGE_SCHEME_SETTINGS_EXPLANATIONS. 2255 getFieldName()); 2256 if (values != null) 2257 { 2258 for (final JSONValue value : values) 2259 { 2260 if (value instanceof JSONObject) 2261 { 2262 final JSONObject valueObject = (JSONObject) value; 2263 final String schemeName = valueObject.getFieldAsString( 2264 NON_CURRENT_ENCODING_FIELD_SCHEME); 2265 if (schemeName == null) 2266 { 2267 continue; 2268 } 2269 2270 final List<String> explanationStrings = new ArrayList<>(); 2271 final List<JSONValue> explanationValues = valueObject.getFieldAsArray( 2272 NON_CURRENT_ENCODING_FIELD_EXPLANATIONS); 2273 if (explanationValues != null) 2274 { 2275 for (final JSONValue explanationValue : explanationValues) 2276 { 2277 if (explanationValue instanceof JSONString) 2278 { 2279 explanationStrings.add( 2280 ((JSONString) explanationValue).stringValue()); 2281 } 2282 } 2283 } 2284 2285 explanationsMap.put(schemeName, explanationStrings); 2286 } 2287 } 2288 } 2289 2290 return Collections.unmodifiableMap(explanationsMap); 2291 } 2292 2293 2294 2295 /** 2296 * Retrieves the value of the specified field as a {@code Date}. 2297 * 2298 * @param field The field whose value is to be retrieved and parsed as a 2299 * {@code Date}. 2300 * 2301 * @return The value of the specified field as a {@code Date}, or 2302 * {@code null} if the field is not contained in the JSON object or 2303 * if its value cannot be parsed as a {@code Date}. 2304 */ 2305 @Nullable() 2306 private Date getDate(@NotNull final PasswordPolicyStateJSONField field) 2307 { 2308 final String stringValue = 2309 passwordPolicyStateObject.getFieldAsString(field.getFieldName()); 2310 if (stringValue == null) 2311 { 2312 return null; 2313 } 2314 2315 try 2316 { 2317 return StaticUtils.decodeRFC3339Time(stringValue); 2318 } 2319 catch (final Exception e) 2320 { 2321 Debug.debugException(e); 2322 return null; 2323 } 2324 } 2325 2326 2327 2328 /** 2329 * Retrieves a string representation of the password policy state information. 2330 * 2331 * @return A string representation of the password policy state information. 2332 */ 2333 @Override() 2334 @NotNull() 2335 public String toString() 2336 { 2337 return passwordPolicyStateObject.toSingleLineString(); 2338 } 2339}