001/* 002 * Copyright 2015-2019 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright (C) 2015-2019 Ping Identity Corporation 007 * 008 * This program is free software; you can redistribute it and/or modify 009 * it under the terms of the GNU General Public License (GPLv2 only) 010 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 011 * as published by the Free Software Foundation. 012 * 013 * This program is distributed in the hope that it will be useful, 014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 016 * GNU General Public License for more details. 017 * 018 * You should have received a copy of the GNU General Public License 019 * along with this program; if not, see <http://www.gnu.org/licenses>. 020 */ 021package com.unboundid.ldap.sdk.unboundidds.extensions; 022 023 024 025import java.util.ArrayList; 026import java.util.Collections; 027import java.util.Iterator; 028import java.util.List; 029 030import com.unboundid.asn1.ASN1Element; 031import com.unboundid.asn1.ASN1OctetString; 032import com.unboundid.asn1.ASN1Sequence; 033import com.unboundid.ldap.sdk.Control; 034import com.unboundid.ldap.sdk.ExtendedRequest; 035import com.unboundid.ldap.sdk.ExtendedResult; 036import com.unboundid.ldap.sdk.LDAPConnection; 037import com.unboundid.ldap.sdk.LDAPException; 038import com.unboundid.ldap.sdk.ResultCode; 039import com.unboundid.util.Debug; 040import com.unboundid.util.NotMutable; 041import com.unboundid.util.ObjectPair; 042import com.unboundid.util.StaticUtils; 043import com.unboundid.util.ThreadSafety; 044import com.unboundid.util.ThreadSafetyLevel; 045import com.unboundid.util.Validator; 046 047import static com.unboundid.ldap.sdk.unboundidds.extensions.ExtOpMessages.*; 048 049 050 051/** 052 * This class provides an implementation of an extended request that can be used 053 * to trigger the delivery of a temporary one-time password reset token to a 054 * specified user. This token can be provided to the password modify extended 055 * request in lieu of the current password for the purpose of performing a self 056 * change and setting a new password. This token cannot be used to authenticate 057 * to the server in any other way, and it can only be used once. The token will 058 * expire after a short period of time, and any attempt to use it after its 059 * expiration will fail. In addition, because this token is only intended for 060 * use in the event that the current password cannot be used (e.g., because it 061 * has been forgotten or the account is locked), a successful bind with the 062 * current password will cause the server to invalidate any password reset token 063 * for that user. 064 * <BR> 065 * <BLOCKQUOTE> 066 * <B>NOTE:</B> This class, and other classes within the 067 * {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only 068 * supported for use against Ping Identity, UnboundID, and 069 * Nokia/Alcatel-Lucent 8661 server products. These classes provide support 070 * for proprietary functionality or for external specifications that are not 071 * considered stable or mature enough to be guaranteed to work in an 072 * interoperable way with other types of LDAP servers. 073 * </BLOCKQUOTE> 074 * <BR> 075 * The server will use the same mechanisms for delivering password reset tokens 076 * as it uses for delivering one-time passwords via the 077 * {@link DeliverOneTimePasswordExtendedRequest}. See the 078 * ds-supported-otp-delivery-mechanism attribute in the root DSE for a list of 079 * the one-time password delivery mechanisms that are configured for use in the 080 * server. 081 * <BR><BR> 082 * This extended request is expected to be used to help applications provide a 083 * secure, automated password reset feature. In the event that a user has 084 * forgotten his/her password, has allowed the password to expire, or has 085 * allowed the account to become locked, the application can collect a 086 * sufficient set of information to identify the user and request that the 087 * server generate and deliver the password reset token to the end user. 088 * <BR><BR> 089 * The OID for this extended request is 1.3.6.1.4.1.30221.2.6.45. It must have 090 * a value with the following encoding: 091 * <PRE> 092 * DeliverPasswordResetTokenRequestValue ::= SEQUENCE { 093 * userDN LDAPDN, 094 * messageSubject [0] OCTET STRING OPTIONAL, 095 * fullTextBeforeToken [1] OCTET STRING OPTIONAL, 096 * fullTextAfterToken [2] OCTET STRING OPTIONAL, 097 * compactTextBeforeToken [3] OCTET STRING OPTIONAL, 098 * compactTextAfterToken [4] OCTET STRING OPTIONAL, 099 * preferredDeliveryMechanism [5] SEQUENCE OF SEQUENCE { 100 * mechanismName OCTET STRING, 101 * recipientID OCTET STRING OPTIONAL }, 102 * ... } 103 * </PRE> 104 * 105 * @see DeliverPasswordResetTokenExtendedResult 106 */ 107@NotMutable() 108@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE) 109public final class DeliverPasswordResetTokenExtendedRequest 110 extends ExtendedRequest 111{ 112 /** 113 * The OID (1.3.6.1.4.1.30221.2.6.45) for the deliver password reset token 114 * extended request. 115 */ 116 public static final String DELIVER_PW_RESET_TOKEN_REQUEST_OID = 117 "1.3.6.1.4.1.30221.2.6.45"; 118 119 120 121 /** 122 * The BER type for the "message subject" element of the value sequence. 123 */ 124 private static final byte MESSAGE_SUBJECT_BER_TYPE = (byte) 0x80; 125 126 127 128 /** 129 * The BER type for the "full text before token" element of the value 130 * sequence. 131 */ 132 private static final byte FULL_TEXT_BEFORE_TOKEN_BER_TYPE = (byte) 0x81; 133 134 135 136 /** 137 * The BER type for the "full text after token" element of the value 138 * sequence. 139 */ 140 private static final byte FULL_TEXT_AFTER_TOKEN_BER_TYPE = (byte) 0x82; 141 142 143 144 /** 145 * The BER type for the "compact text before token" element of the value 146 * sequence. 147 */ 148 private static final byte COMPACT_TEXT_BEFORE_TOKEN_BER_TYPE = (byte) 0x83; 149 150 151 152 /** 153 * The BER type for the "compact text after token" element of the value 154 * sequence. 155 */ 156 private static final byte COMPACT_TEXT_AFTER_TOKEN_BER_TYPE = (byte) 0x84; 157 158 159 160 /** 161 * The BER type for the "preferred delivery mechanism" element of the value 162 * sequence. 163 */ 164 private static final byte PREFERRED_DELIVERY_MECHANISM_BER_TYPE = (byte) 0xA5; 165 166 167 168 /** 169 * The serial version UID for this serializable class. 170 */ 171 private static final long serialVersionUID = 7608072810737347230L; 172 173 174 175 // An ordered list of the preferred delivery mechanisms for the token, 176 // paired with an optional recipient ID for each mechanism. 177 private final List<ObjectPair<String, String>> preferredDeliveryMechanisms; 178 179 // The text to include after the token in a compact message. 180 private final String compactTextAfterToken; 181 182 // The text to include before the token in a compact message. 183 private final String compactTextBeforeToken; 184 185 // The text to include after the token in a message without size constraints. 186 private final String fullTextAfterToken; 187 188 // The text to include before the token in a message without size constraints. 189 private final String fullTextBeforeToken; 190 191 // The text to use as the message subject. 192 private final String messageSubject; 193 194 // The DN of the user to whom the password reset token should be delivered. 195 private final String userDN; 196 197 198 199 /** 200 * Creates a new deliver password reset token extended request with the 201 * provided information. 202 * 203 * @param userDN The DN of the user to whom the 204 * password reset token should be 205 * generated. 206 * @param preferredDeliveryMechanisms An optional ordered list of preferred 207 * delivery mechanisms that should be 208 * used to deliver the token to the user. 209 * It may be {@code null} or empty to 210 * allow the server to select an 211 * appropriate delivery mechanism. If it 212 * is non-{@code null} and non-empty, 213 * then only the listed mechanisms will 214 * be considered for use, even if the 215 * server supports alternate mechanisms 216 * not included in this list. 217 */ 218 public DeliverPasswordResetTokenExtendedRequest(final String userDN, 219 final String... preferredDeliveryMechanisms) 220 { 221 this(userDN, preferredMechanismsToList(preferredDeliveryMechanisms)); 222 } 223 224 225 226 /** 227 * Creates a new deliver password reset token extended request with the 228 * provided information. 229 * 230 * @param userDN The DN of the user to whom the 231 * password reset token should be 232 * generated. 233 * @param preferredDeliveryMechanisms An optional ordered list of preferred 234 * delivery mechanisms that should be 235 * used to deliver the token to the user. 236 * It may be {@code null} or empty to 237 * allow the server to select an 238 * appropriate delivery mechanism. If it 239 * is non-{@code null} and non-empty, 240 * then only the listed mechanisms will 241 * be considered for use, even if the 242 * server supports alternate mechanisms 243 * not included in this list. Each 244 * {@code ObjectPair} item must have 245 * a non-{@code null} value for the first 246 * element, which is the name of the 247 * target delivery mechanism. It may 248 * optionally have a non-{@code null} 249 * value for the second element, which is 250 * a recipient ID to use for that 251 * mechanism (e.g., the target mobile 252 * phone number for SMS delivery, an 253 * email address for email delivery, 254 * etc.). If no recipient ID is provided 255 * for a mechanism, then the server will 256 * attempt to select a value for the 257 * user. 258 * @param controls An optional set of controls to include 259 * in the request. It may be 260 * {@code null} or empty if no controls 261 * should be included in the request. 262 */ 263 public DeliverPasswordResetTokenExtendedRequest(final String userDN, 264 final List<ObjectPair<String,String>> preferredDeliveryMechanisms, 265 final Control... controls) 266 { 267 this(userDN, null, null, null, null, null, preferredDeliveryMechanisms, 268 controls); 269 } 270 271 272 273 /** 274 * Creates a new deliver password reset token extended request with the 275 * provided information. 276 * 277 * @param userDN The DN of the user to whom the 278 * password reset token should be 279 * generated. 280 * @param messageSubject The text (if any) that should be used 281 * as the message subject if the delivery 282 * mechanism accepts a subject. This may 283 * be {@code null} if no subject is 284 * required or a subject should be 285 * automatically generated. 286 * @param fullTextBeforeToken The text (if any) that should appear 287 * before the generated password reset 288 * token in the message delivered to the 289 * user via a delivery mechanism that 290 * does not impose significant 291 * constraints on message size. This may 292 * be {@code null} if no text is required 293 * before the token. 294 * @param fullTextAfterToken The text (if any) that should appear 295 * after the generated password reset 296 * token in the message delivered to the 297 * user via a delivery mechanism that 298 * does not impose significant 299 * constraints on message size. This may 300 * be {@code null} if no text is required 301 * after the token. 302 * @param compactTextBeforeToken The text (if any) that should appear 303 * before the generated password reset 304 * token in the message delivered to the 305 * user via a delivery mechanism that 306 * imposes significant constraints on 307 * message size. This may be 308 * {@code null} if no text is required 309 * before the token. 310 * @param compactTextAfterToken The text (if any) that should appear 311 * after the generated password reset 312 * token in the message delivered to the 313 * user via a delivery mechanism that 314 * imposes significant constraints on 315 * message size. This may be 316 * {@code null} if no text is required 317 * after the token. 318 * @param preferredDeliveryMechanisms An optional ordered list of preferred 319 * delivery mechanisms that should be 320 * used to deliver the token to the user. 321 * It may be {@code null} or empty to 322 * allow the server to select an 323 * appropriate delivery mechanism. If it 324 * is non-{@code null} and non-empty, 325 * then only the listed mechanisms will 326 * be considered for use, even if the 327 * server supports alternate mechanisms 328 * not included in this list. Each 329 * {@code ObjectPair} item must have 330 * a non-{@code null} value for the first 331 * element, which is the name of the 332 * target delivery mechanism. It may 333 * optionally have a non-{@code null} 334 * value for the second element, which is 335 * a recipient ID to use for that 336 * mechanism (e.g., the target mobile 337 * phone number for SMS delivery, an 338 * email address for email delivery, 339 * etc.). If no recipient ID is provided 340 * for a mechanism, then the server will 341 * attempt to select a value for the 342 * user. 343 * @param controls An optional set of controls to include 344 * in the request. It may be 345 * {@code null} or empty if no controls 346 * should be included in the request. 347 */ 348 public DeliverPasswordResetTokenExtendedRequest(final String userDN, 349 final String messageSubject, final String fullTextBeforeToken, 350 final String fullTextAfterToken, 351 final String compactTextBeforeToken, 352 final String compactTextAfterToken, 353 final List<ObjectPair<String,String>> preferredDeliveryMechanisms, 354 final Control... controls) 355 { 356 super(DELIVER_PW_RESET_TOKEN_REQUEST_OID, 357 encodeValue(userDN, messageSubject, fullTextBeforeToken, 358 fullTextAfterToken, compactTextBeforeToken, compactTextAfterToken, 359 preferredDeliveryMechanisms), controls); 360 361 this.userDN = userDN; 362 this.messageSubject = messageSubject; 363 this.fullTextBeforeToken = fullTextBeforeToken; 364 this.fullTextAfterToken = fullTextAfterToken; 365 this.compactTextBeforeToken = compactTextBeforeToken; 366 this.compactTextAfterToken = compactTextAfterToken; 367 368 if (preferredDeliveryMechanisms == null) 369 { 370 this.preferredDeliveryMechanisms = Collections.emptyList(); 371 } 372 else 373 { 374 this.preferredDeliveryMechanisms = Collections.unmodifiableList( 375 new ArrayList<>(preferredDeliveryMechanisms)); 376 } 377 } 378 379 380 381 /** 382 * Creates a new deliver password reset token extended request that is decoded 383 * from the provided extended request. 384 * 385 * @param request The generic extended request to decode as a deliver 386 * password reset token request. It must not be 387 * {@code null}. 388 * 389 * @throws LDAPException If an unexpected problem occurs. 390 */ 391 public DeliverPasswordResetTokenExtendedRequest(final ExtendedRequest request) 392 throws LDAPException 393 { 394 super(request); 395 396 final ASN1OctetString value = request.getValue(); 397 if (value == null) 398 { 399 throw new LDAPException(ResultCode.DECODING_ERROR, 400 ERR_DELIVER_PW_RESET_TOKEN_REQUEST_NO_VALUE.get()); 401 } 402 403 try 404 { 405 final ASN1Element[] elements = 406 ASN1Sequence.decodeAsSequence(value.getValue()).elements(); 407 userDN = ASN1OctetString.decodeAsOctetString(elements[0]).stringValue(); 408 409 String subject = null; 410 String fullBefore = null; 411 String fullAfter = null; 412 String compactBefore = null; 413 String compactAfter = null; 414 final ArrayList<ObjectPair<String,String>> pdmList = new ArrayList<>(10); 415 for (int i=1; i < elements.length; i++) 416 { 417 switch (elements[i].getType()) 418 { 419 case MESSAGE_SUBJECT_BER_TYPE: 420 subject = 421 ASN1OctetString.decodeAsOctetString(elements[i]).stringValue(); 422 break; 423 424 case FULL_TEXT_BEFORE_TOKEN_BER_TYPE: 425 fullBefore = 426 ASN1OctetString.decodeAsOctetString(elements[i]).stringValue(); 427 break; 428 429 case FULL_TEXT_AFTER_TOKEN_BER_TYPE: 430 fullAfter = 431 ASN1OctetString.decodeAsOctetString(elements[i]).stringValue(); 432 break; 433 434 case COMPACT_TEXT_BEFORE_TOKEN_BER_TYPE: 435 compactBefore = 436 ASN1OctetString.decodeAsOctetString(elements[i]).stringValue(); 437 break; 438 439 case COMPACT_TEXT_AFTER_TOKEN_BER_TYPE: 440 compactAfter = 441 ASN1OctetString.decodeAsOctetString(elements[i]).stringValue(); 442 break; 443 444 case PREFERRED_DELIVERY_MECHANISM_BER_TYPE: 445 final ASN1Element[] pdmElements = 446 ASN1Sequence.decodeAsSequence(elements[i]).elements(); 447 for (final ASN1Element e : pdmElements) 448 { 449 final ASN1Element[] mechElements = 450 ASN1Sequence.decodeAsSequence(e).elements(); 451 final String mech = ASN1OctetString.decodeAsOctetString( 452 mechElements[0]).stringValue(); 453 454 final String recipientID; 455 if (mechElements.length > 1) 456 { 457 recipientID = ASN1OctetString.decodeAsOctetString( 458 mechElements[1]).stringValue(); 459 } 460 else 461 { 462 recipientID = null; 463 } 464 465 pdmList.add(new ObjectPair<>(mech, recipientID)); 466 } 467 break; 468 469 default: 470 throw new LDAPException(ResultCode.DECODING_ERROR, 471 ERR_DELIVER_PW_RESET_TOKEN_REQUEST_UNEXPECTED_TYPE.get( 472 StaticUtils.toHex(elements[i].getType()))); 473 } 474 } 475 476 preferredDeliveryMechanisms = Collections.unmodifiableList(pdmList); 477 messageSubject = subject; 478 fullTextBeforeToken = fullBefore; 479 fullTextAfterToken = fullAfter; 480 compactTextBeforeToken = compactBefore; 481 compactTextAfterToken = compactAfter; 482 } 483 catch (final LDAPException le) 484 { 485 Debug.debugException(le); 486 throw le; 487 } 488 catch (final Exception e) 489 { 490 Debug.debugException(e); 491 throw new LDAPException(ResultCode.DECODING_ERROR, 492 ERR_DELIVER_PW_RESET_TOKEN_REQUEST_ERROR_DECODING_VALUE.get( 493 StaticUtils.getExceptionMessage(e)), 494 e); 495 } 496 } 497 498 499 500 /** 501 * Encodes the provided set of preferred delivery mechanisms into a form 502 * acceptable to the constructor that expects an object pair. All of the 503 * recipient IDs will be {@code null}. 504 * 505 * @param preferredDeliveryMechanisms An optional ordered list of preferred 506 * delivery mechanisms that should be 507 * used to deliver the token to the user. 508 * It may be {@code null} or empty to 509 * allow the server to select an 510 * appropriate delivery mechanism. If it 511 * is non-{@code null} and non-empty, 512 * then only the listed mechanisms will 513 * be considered for use, even if the 514 * server supports alternate mechanisms 515 * not included in this list. 516 * 517 * @return The resulting list of preferred delivery mechanisms with 518 * {@code null} recipient IDs. 519 */ 520 private static List<ObjectPair<String,String>> preferredMechanismsToList( 521 final String... preferredDeliveryMechanisms) 522 { 523 if (preferredDeliveryMechanisms == null) 524 { 525 return null; 526 } 527 528 final ArrayList<ObjectPair<String,String>> l = 529 new ArrayList<>(preferredDeliveryMechanisms.length); 530 for (final String s : preferredDeliveryMechanisms) 531 { 532 l.add(new ObjectPair<String,String>(s, null)); 533 } 534 return l; 535 } 536 537 538 539 /** 540 * Creates an ASN.1 octet string suitable for use as the value of this 541 * extended request. 542 * 543 * @param userDN The DN of the user to whom the 544 * password reset token should be 545 * generated. 546 * @param messageSubject The text (if any) that should be used 547 * as the message subject if the delivery 548 * mechanism accepts a subject. This may 549 * be {@code null} if no subject is 550 * required or a subject should be 551 * automatically generated. 552 * @param fullTextBeforeToken The text (if any) that should appear 553 * before the generated password reset 554 * token in the message delivered to the 555 * user via a delivery mechanism that 556 * does not impose significant 557 * constraints on message size. This may 558 * be {@code null} if no text is required 559 * before the token. 560 * @param fullTextAfterToken The text (if any) that should appear 561 * after the generated password reset 562 * token in the message delivered to the 563 * user via a delivery mechanism that 564 * does not impose significant 565 * constraints on message size. This may 566 * be {@code null} if no text is required 567 * after the token. 568 * @param compactTextBeforeToken The text (if any) that should appear 569 * before the generated password reset 570 * token in the message delivered to the 571 * user via a delivery mechanism that 572 * imposes significant constraints on 573 * message size. This may be 574 * {@code null} if no text is required 575 * before the token. 576 * @param compactTextAfterToken The text (if any) that should appear 577 * after the generated password reset 578 * token in the message delivered to the 579 * user via a delivery mechanism that 580 * imposes significant constraints on 581 * message size. This may be 582 * {@code null} if no text is required 583 * after the token. 584 * @param preferredDeliveryMechanisms An optional ordered list of preferred 585 * delivery mechanisms that should be 586 * used to deliver the token to the user. 587 * It may be {@code null} or empty to 588 * allow the server to select an 589 * appropriate delivery mechanism. If it 590 * is non-{@code null} and non-empty, 591 * then only the listed mechanisms will 592 * be considered for use, even if the 593 * server supports alternate mechanisms 594 * not included in this list. Each 595 * {@code ObjectPair} item must have 596 * a non-{@code null} value for the first 597 * element, which is the name of the 598 * target delivery mechanism. It may 599 * optionally have a non-{@code null} 600 * value for the second element, which is 601 * a recipient ID to use for that 602 * mechanism (e.g., the target mobile 603 * phone number for SMS delivery, an 604 * email address for email delivery, 605 * etc.). If no recipient ID is provided 606 * for a mechanism, then the server will 607 * attempt to select a value for the 608 * user. 609 * 610 * @return The ASN.1 octet string containing the encoded request value. 611 */ 612 private static ASN1OctetString encodeValue(final String userDN, 613 final String messageSubject, final String fullTextBeforeToken, 614 final String fullTextAfterToken, final String compactTextBeforeToken, 615 final String compactTextAfterToken, 616 final List<ObjectPair<String,String>> preferredDeliveryMechanisms) 617 { 618 Validator.ensureNotNull(userDN); 619 620 final ArrayList<ASN1Element> elements = new ArrayList<>(7); 621 elements.add(new ASN1OctetString(userDN)); 622 623 if (messageSubject != null) 624 { 625 elements.add(new ASN1OctetString(MESSAGE_SUBJECT_BER_TYPE, 626 messageSubject)); 627 } 628 629 if (fullTextBeforeToken != null) 630 { 631 elements.add(new ASN1OctetString(FULL_TEXT_BEFORE_TOKEN_BER_TYPE, 632 fullTextBeforeToken)); 633 } 634 635 if (fullTextAfterToken != null) 636 { 637 elements.add(new ASN1OctetString(FULL_TEXT_AFTER_TOKEN_BER_TYPE, 638 fullTextAfterToken)); 639 } 640 641 if (compactTextBeforeToken != null) 642 { 643 elements.add(new ASN1OctetString(COMPACT_TEXT_BEFORE_TOKEN_BER_TYPE, 644 compactTextBeforeToken)); 645 } 646 647 if (compactTextAfterToken != null) 648 { 649 elements.add(new ASN1OctetString(COMPACT_TEXT_AFTER_TOKEN_BER_TYPE, 650 compactTextAfterToken)); 651 } 652 653 if ((preferredDeliveryMechanisms != null) && 654 (! preferredDeliveryMechanisms.isEmpty())) 655 { 656 final ArrayList<ASN1Element> pdmElements = 657 new ArrayList<>(preferredDeliveryMechanisms.size()); 658 for (final ObjectPair<String,String> p : preferredDeliveryMechanisms) 659 { 660 if (p.getSecond() == null) 661 { 662 pdmElements.add(new ASN1Sequence( 663 new ASN1OctetString(p.getFirst()))); 664 } 665 else 666 { 667 pdmElements.add(new ASN1Sequence( 668 new ASN1OctetString(p.getFirst()), 669 new ASN1OctetString(p.getSecond()))); 670 } 671 } 672 673 elements.add(new ASN1Sequence(PREFERRED_DELIVERY_MECHANISM_BER_TYPE, 674 pdmElements)); 675 } 676 677 return new ASN1OctetString(new ASN1Sequence(elements).encode()); 678 } 679 680 681 682 /** 683 * Retrieves the DN of the user to whom the password reset token should be 684 * delivered. 685 * 686 * @return The DN of the user to whom the password reset token should be 687 * delivered. 688 */ 689 public String getUserDN() 690 { 691 return userDN; 692 } 693 694 695 696 /** 697 * Retrieves the text (if any) that should be used as the message subject for 698 * delivery mechanisms that can make use of a subject. 699 * 700 * @return The text that should be used as the message subject for delivery 701 * mechanisms that can make use of a subject, or {@code null} if no 702 * subject should be used, or if the delivery mechanism should 703 * attempt to automatically determine a subject. 704 */ 705 public String getMessageSubject() 706 { 707 return messageSubject; 708 } 709 710 711 712 /** 713 * Retrieves the text (if any) that should appear before the single-use token 714 * in the message delivered to the user via a mechanism that does not impose 715 * significant constraints on message size. 716 * 717 * @return The text that should appear before the single-use token in the 718 * message delivered to the user via a mechanism that does not impose 719 * significant constraints on message size, or {@code null} if there 720 * should not be any text before the token. 721 */ 722 public String getFullTextBeforeToken() 723 { 724 return fullTextBeforeToken; 725 } 726 727 728 729 /** 730 * Retrieves the text (if any) that should appear after the single-use token 731 * in the message delivered to the user via a mechanism that does not impose 732 * significant constraints on message size. 733 * 734 * @return The text that should appear after the single-use token in the 735 * message delivered to the user via a mechanism that does not impose 736 * significant constraints on message size, or {@code null} if there 737 * should not be any text after the token. 738 */ 739 public String getFullTextAfterToken() 740 { 741 return fullTextAfterToken; 742 } 743 744 745 746 /** 747 * Retrieves the text (if any) that should appear before the single-use token 748 * in the message delivered to the user via a mechanism that imposes 749 * significant constraints on message size. 750 * 751 * @return The text that should appear before the single-use token in the 752 * message delivered to the user via a mechanism that imposes 753 * significant constraints on message size, or {@code null} if there 754 * should not be any text before the token. 755 */ 756 public String getCompactTextBeforeToken() 757 { 758 return compactTextBeforeToken; 759 } 760 761 762 763 /** 764 * Retrieves the text (if any) that should appear after the single-use token 765 * in the message delivered to the user via a mechanism that imposes 766 * significant constraints on message size. 767 * 768 * @return The text that should appear after the single-use token in the 769 * message delivered to the user via a mechanism that imposes 770 * significant constraints on message size, or {@code null} if there 771 * should not be any text after the token. 772 */ 773 public String getCompactTextAfterToken() 774 { 775 return compactTextAfterToken; 776 } 777 778 779 780 /** 781 * Retrieves an ordered list of the preferred delivery mechanisms that should 782 * be used to provide the password reset token to the user, optionally paired 783 * with a mechanism-specific recipient ID (e.g., a mobile phone number for SMS 784 * delivery, or an email address for email delivery) that can be used in the 785 * delivery. If this list is non-empty, then the server will use the first 786 * mechanism in the list that the server supports and is available for the 787 * target user, and the server will only consider mechanisms in the provided 788 * list even if the server supports alternate mechanisms that are not 789 * included. If this list is empty, then the server will attempt to select an 790 * appropriate delivery mechanism for the user. 791 * 792 * @return An ordered list of the preferred delivery mechanisms for the 793 * password reset token, or an empty list if none were provided. 794 */ 795 public List<ObjectPair<String,String>> getPreferredDeliveryMechanisms() 796 { 797 return preferredDeliveryMechanisms; 798 } 799 800 801 802 /** 803 * {@inheritDoc} 804 */ 805 @Override() 806 public DeliverPasswordResetTokenExtendedResult process( 807 final LDAPConnection connection, final int depth) 808 throws LDAPException 809 { 810 final ExtendedResult extendedResponse = super.process(connection, depth); 811 return new DeliverPasswordResetTokenExtendedResult(extendedResponse); 812 } 813 814 815 816 /** 817 * {@inheritDoc}. 818 */ 819 @Override() 820 public DeliverPasswordResetTokenExtendedRequest duplicate() 821 { 822 return duplicate(getControls()); 823 } 824 825 826 827 /** 828 * {@inheritDoc}. 829 */ 830 @Override() 831 public DeliverPasswordResetTokenExtendedRequest duplicate( 832 final Control[] controls) 833 { 834 final DeliverPasswordResetTokenExtendedRequest r = 835 new DeliverPasswordResetTokenExtendedRequest(userDN, 836 messageSubject, fullTextBeforeToken, fullTextAfterToken, 837 compactTextBeforeToken, compactTextAfterToken, 838 preferredDeliveryMechanisms, controls); 839 r.setResponseTimeoutMillis(getResponseTimeoutMillis(null)); 840 return r; 841 } 842 843 844 845 /** 846 * {@inheritDoc} 847 */ 848 @Override() 849 public String getExtendedRequestName() 850 { 851 return INFO_EXTENDED_REQUEST_NAME_DELIVER_PW_RESET_TOKEN.get(); 852 } 853 854 855 856 /** 857 * {@inheritDoc} 858 */ 859 @Override() 860 public void toString(final StringBuilder buffer) 861 { 862 buffer.append("DeliverPasswordResetTokenExtendedRequest(userDN='"); 863 buffer.append(userDN); 864 buffer.append('\''); 865 866 if (messageSubject != null) 867 { 868 buffer.append(", messageSubject='"); 869 buffer.append(messageSubject); 870 buffer.append('\''); 871 } 872 873 if (fullTextBeforeToken != null) 874 { 875 buffer.append(", fullTextBeforeToken='"); 876 buffer.append(fullTextBeforeToken); 877 buffer.append('\''); 878 } 879 880 if (fullTextAfterToken != null) 881 { 882 buffer.append(", fullTextAfterToken='"); 883 buffer.append(fullTextAfterToken); 884 buffer.append('\''); 885 } 886 887 if (compactTextBeforeToken != null) 888 { 889 buffer.append(", compactTextBeforeToken='"); 890 buffer.append(compactTextBeforeToken); 891 buffer.append('\''); 892 } 893 894 if (compactTextAfterToken != null) 895 { 896 buffer.append(", compactTextAfterToken='"); 897 buffer.append(compactTextAfterToken); 898 buffer.append('\''); 899 } 900 901 if (preferredDeliveryMechanisms != null) 902 { 903 buffer.append(", preferredDeliveryMechanisms={"); 904 905 final Iterator<ObjectPair<String,String>> iterator = 906 preferredDeliveryMechanisms.iterator(); 907 while (iterator.hasNext()) 908 { 909 final ObjectPair<String,String> p = iterator.next(); 910 buffer.append('\''); 911 buffer.append(p.getFirst()); 912 if (p.getSecond() != null) 913 { 914 buffer.append('('); 915 buffer.append(p.getSecond()); 916 buffer.append(')'); 917 } 918 buffer.append('\''); 919 if (iterator.hasNext()) 920 { 921 buffer.append(','); 922 } 923 } 924 } 925 926 final Control[] controls = getControls(); 927 if (controls.length > 0) 928 { 929 buffer.append(", controls={"); 930 for (int i=0; i < controls.length; i++) 931 { 932 if (i > 0) 933 { 934 buffer.append(", "); 935 } 936 937 buffer.append(controls[i]); 938 } 939 buffer.append('}'); 940 } 941 942 buffer.append(')'); 943 } 944}