001/* 002 * Copyright 2015-2018 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright (C) 2015-2018 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 Alcatel-Lucent 8661 069 * server products. These classes provide support for proprietary 070 * functionality or for external specifications that are not considered stable 071 * or mature enough to be guaranteed to work in an interoperable way with 072 * 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<ObjectPair<String,String>>( 376 preferredDeliveryMechanisms)); 377 } 378 } 379 380 381 382 /** 383 * Creates a new deliver password reset token extended request that is decoded 384 * from the provided extended request. 385 * 386 * @param request The generic extended request to decode as a deliver 387 * password reset token request. It must not be 388 * {@code null}. 389 * 390 * @throws LDAPException If an unexpected problem occurs. 391 */ 392 public DeliverPasswordResetTokenExtendedRequest(final ExtendedRequest request) 393 throws LDAPException 394 { 395 super(request); 396 397 final ASN1OctetString value = request.getValue(); 398 if (value == null) 399 { 400 throw new LDAPException(ResultCode.DECODING_ERROR, 401 ERR_DELIVER_PW_RESET_TOKEN_REQUEST_NO_VALUE.get()); 402 } 403 404 try 405 { 406 final ASN1Element[] elements = 407 ASN1Sequence.decodeAsSequence(value.getValue()).elements(); 408 userDN = ASN1OctetString.decodeAsOctetString(elements[0]).stringValue(); 409 410 String subject = null; 411 String fullBefore = null; 412 String fullAfter = null; 413 String compactBefore = null; 414 String compactAfter = null; 415 final ArrayList<ObjectPair<String,String>> pdmList = 416 new ArrayList<ObjectPair<String,String>>(10); 417 for (int i=1; i < elements.length; i++) 418 { 419 switch (elements[i].getType()) 420 { 421 case MESSAGE_SUBJECT_BER_TYPE: 422 subject = 423 ASN1OctetString.decodeAsOctetString(elements[i]).stringValue(); 424 break; 425 426 case FULL_TEXT_BEFORE_TOKEN_BER_TYPE: 427 fullBefore = 428 ASN1OctetString.decodeAsOctetString(elements[i]).stringValue(); 429 break; 430 431 case FULL_TEXT_AFTER_TOKEN_BER_TYPE: 432 fullAfter = 433 ASN1OctetString.decodeAsOctetString(elements[i]).stringValue(); 434 break; 435 436 case COMPACT_TEXT_BEFORE_TOKEN_BER_TYPE: 437 compactBefore = 438 ASN1OctetString.decodeAsOctetString(elements[i]).stringValue(); 439 break; 440 441 case COMPACT_TEXT_AFTER_TOKEN_BER_TYPE: 442 compactAfter = 443 ASN1OctetString.decodeAsOctetString(elements[i]).stringValue(); 444 break; 445 446 case PREFERRED_DELIVERY_MECHANISM_BER_TYPE: 447 final ASN1Element[] pdmElements = 448 ASN1Sequence.decodeAsSequence(elements[i]).elements(); 449 for (final ASN1Element e : pdmElements) 450 { 451 final ASN1Element[] mechElements = 452 ASN1Sequence.decodeAsSequence(e).elements(); 453 final String mech = ASN1OctetString.decodeAsOctetString( 454 mechElements[0]).stringValue(); 455 456 final String recipientID; 457 if (mechElements.length > 1) 458 { 459 recipientID = ASN1OctetString.decodeAsOctetString( 460 mechElements[1]).stringValue(); 461 } 462 else 463 { 464 recipientID = null; 465 } 466 467 pdmList.add(new ObjectPair<String,String>(mech, recipientID)); 468 } 469 break; 470 471 default: 472 throw new LDAPException(ResultCode.DECODING_ERROR, 473 ERR_DELIVER_PW_RESET_TOKEN_REQUEST_UNEXPECTED_TYPE.get( 474 StaticUtils.toHex(elements[i].getType()))); 475 } 476 } 477 478 preferredDeliveryMechanisms = Collections.unmodifiableList(pdmList); 479 messageSubject = subject; 480 fullTextBeforeToken = fullBefore; 481 fullTextAfterToken = fullAfter; 482 compactTextBeforeToken = compactBefore; 483 compactTextAfterToken = compactAfter; 484 } 485 catch (final LDAPException le) 486 { 487 Debug.debugException(le); 488 throw le; 489 } 490 catch (final Exception e) 491 { 492 Debug.debugException(e); 493 throw new LDAPException(ResultCode.DECODING_ERROR, 494 ERR_DELIVER_PW_RESET_TOKEN_REQUEST_ERROR_DECODING_VALUE.get( 495 StaticUtils.getExceptionMessage(e)), 496 e); 497 } 498 } 499 500 501 502 /** 503 * Encodes the provided set of preferred delivery mechanisms into a form 504 * acceptable to the constructor that expects an object pair. All of the 505 * recipient IDs will be {@code null}. 506 * 507 * @param preferredDeliveryMechanisms An optional ordered list of preferred 508 * delivery mechanisms that should be 509 * used to deliver the token to the user. 510 * It may be {@code null} or empty to 511 * allow the server to select an 512 * appropriate delivery mechanism. If it 513 * is non-{@code null} and non-empty, 514 * then only the listed mechanisms will 515 * be considered for use, even if the 516 * server supports alternate mechanisms 517 * not included in this list. 518 * 519 * @return The resulting list of preferred delivery mechanisms with 520 * {@code null} recipient IDs. 521 */ 522 private static List<ObjectPair<String,String>> preferredMechanismsToList( 523 final String... preferredDeliveryMechanisms) 524 { 525 if (preferredDeliveryMechanisms == null) 526 { 527 return null; 528 } 529 530 final ArrayList<ObjectPair<String,String>> l = 531 new ArrayList<ObjectPair<String,String>>( 532 preferredDeliveryMechanisms.length); 533 for (final String s : preferredDeliveryMechanisms) 534 { 535 l.add(new ObjectPair<String,String>(s, null)); 536 } 537 return l; 538 } 539 540 541 542 /** 543 * Creates an ASN.1 octet string suitable for use as the value of this 544 * extended request. 545 * 546 * @param userDN The DN of the user to whom the 547 * password reset token should be 548 * generated. 549 * @param messageSubject The text (if any) that should be used 550 * as the message subject if the delivery 551 * mechanism accepts a subject. This may 552 * be {@code null} if no subject is 553 * required or a subject should be 554 * automatically generated. 555 * @param fullTextBeforeToken The text (if any) that should appear 556 * before the generated password reset 557 * token in the message delivered to the 558 * user via a delivery mechanism that 559 * does not impose significant 560 * constraints on message size. This may 561 * be {@code null} if no text is required 562 * before the token. 563 * @param fullTextAfterToken The text (if any) that should appear 564 * after the generated password reset 565 * token in the message delivered to the 566 * user via a delivery mechanism that 567 * does not impose significant 568 * constraints on message size. This may 569 * be {@code null} if no text is required 570 * after the token. 571 * @param compactTextBeforeToken The text (if any) that should appear 572 * before the generated password reset 573 * token in the message delivered to the 574 * user via a delivery mechanism that 575 * imposes significant constraints on 576 * message size. This may be 577 * {@code null} if no text is required 578 * before the token. 579 * @param compactTextAfterToken The text (if any) that should appear 580 * after the generated password reset 581 * token in the message delivered to the 582 * user via a delivery mechanism that 583 * imposes significant constraints on 584 * message size. This may be 585 * {@code null} if no text is required 586 * after the token. 587 * @param preferredDeliveryMechanisms An optional ordered list of preferred 588 * delivery mechanisms that should be 589 * used to deliver the token to the user. 590 * It may be {@code null} or empty to 591 * allow the server to select an 592 * appropriate delivery mechanism. If it 593 * is non-{@code null} and non-empty, 594 * then only the listed mechanisms will 595 * be considered for use, even if the 596 * server supports alternate mechanisms 597 * not included in this list. Each 598 * {@code ObjectPair} item must have 599 * a non-{@code null} value for the first 600 * element, which is the name of the 601 * target delivery mechanism. It may 602 * optionally have a non-{@code null} 603 * value for the second element, which is 604 * a recipient ID to use for that 605 * mechanism (e.g., the target mobile 606 * phone number for SMS delivery, an 607 * email address for email delivery, 608 * etc.). If no recipient ID is provided 609 * for a mechanism, then the server will 610 * attempt to select a value for the 611 * user. 612 * 613 * @return The ASN.1 octet string containing the encoded request value. 614 */ 615 private static ASN1OctetString encodeValue(final String userDN, 616 final String messageSubject, final String fullTextBeforeToken, 617 final String fullTextAfterToken, final String compactTextBeforeToken, 618 final String compactTextAfterToken, 619 final List<ObjectPair<String,String>> preferredDeliveryMechanisms) 620 { 621 Validator.ensureNotNull(userDN); 622 623 final ArrayList<ASN1Element> elements = new ArrayList<ASN1Element>(7); 624 elements.add(new ASN1OctetString(userDN)); 625 626 if (messageSubject != null) 627 { 628 elements.add(new ASN1OctetString(MESSAGE_SUBJECT_BER_TYPE, 629 messageSubject)); 630 } 631 632 if (fullTextBeforeToken != null) 633 { 634 elements.add(new ASN1OctetString(FULL_TEXT_BEFORE_TOKEN_BER_TYPE, 635 fullTextBeforeToken)); 636 } 637 638 if (fullTextAfterToken != null) 639 { 640 elements.add(new ASN1OctetString(FULL_TEXT_AFTER_TOKEN_BER_TYPE, 641 fullTextAfterToken)); 642 } 643 644 if (compactTextBeforeToken != null) 645 { 646 elements.add(new ASN1OctetString(COMPACT_TEXT_BEFORE_TOKEN_BER_TYPE, 647 compactTextBeforeToken)); 648 } 649 650 if (compactTextAfterToken != null) 651 { 652 elements.add(new ASN1OctetString(COMPACT_TEXT_AFTER_TOKEN_BER_TYPE, 653 compactTextAfterToken)); 654 } 655 656 if ((preferredDeliveryMechanisms != null) && 657 (! preferredDeliveryMechanisms.isEmpty())) 658 { 659 final ArrayList<ASN1Element> pdmElements = 660 new ArrayList<ASN1Element>(preferredDeliveryMechanisms.size()); 661 for (final ObjectPair<String,String> p : preferredDeliveryMechanisms) 662 { 663 if (p.getSecond() == null) 664 { 665 pdmElements.add(new ASN1Sequence( 666 new ASN1OctetString(p.getFirst()))); 667 } 668 else 669 { 670 pdmElements.add(new ASN1Sequence( 671 new ASN1OctetString(p.getFirst()), 672 new ASN1OctetString(p.getSecond()))); 673 } 674 } 675 676 elements.add(new ASN1Sequence(PREFERRED_DELIVERY_MECHANISM_BER_TYPE, 677 pdmElements)); 678 } 679 680 return new ASN1OctetString(new ASN1Sequence(elements).encode()); 681 } 682 683 684 685 /** 686 * Retrieves the DN of the user to whom the password reset token should be 687 * delivered. 688 * 689 * @return The DN of the user to whom the password reset token should be 690 * delivered. 691 */ 692 public String getUserDN() 693 { 694 return userDN; 695 } 696 697 698 699 /** 700 * Retrieves the text (if any) that should be used as the message subject for 701 * delivery mechanisms that can make use of a subject. 702 * 703 * @return The text that should be used as the message subject for delivery 704 * mechanisms that can make use of a subject, or {@code null} if no 705 * subject should be used, or if the delivery mechanism should 706 * attempt to automatically determine a subject. 707 */ 708 public String getMessageSubject() 709 { 710 return messageSubject; 711 } 712 713 714 715 /** 716 * Retrieves the text (if any) that should appear before the single-use token 717 * in the message delivered to the user via a mechanism that does not impose 718 * significant constraints on message size. 719 * 720 * @return The text that should appear before the single-use token in the 721 * message delivered to the user via a mechanism that does not impose 722 * significant constraints on message size, or {@code null} if there 723 * should not be any text before the token. 724 */ 725 public String getFullTextBeforeToken() 726 { 727 return fullTextBeforeToken; 728 } 729 730 731 732 /** 733 * Retrieves the text (if any) that should appear after the single-use token 734 * in the message delivered to the user via a mechanism that does not impose 735 * significant constraints on message size. 736 * 737 * @return The text that should appear after the single-use token in the 738 * message delivered to the user via a mechanism that does not impose 739 * significant constraints on message size, or {@code null} if there 740 * should not be any text after the token. 741 */ 742 public String getFullTextAfterToken() 743 { 744 return fullTextAfterToken; 745 } 746 747 748 749 /** 750 * Retrieves the text (if any) that should appear before the single-use token 751 * in the message delivered to the user via a mechanism that imposes 752 * significant constraints on message size. 753 * 754 * @return The text that should appear before the single-use token in the 755 * message delivered to the user via a mechanism that imposes 756 * significant constraints on message size, or {@code null} if there 757 * should not be any text before the token. 758 */ 759 public String getCompactTextBeforeToken() 760 { 761 return compactTextBeforeToken; 762 } 763 764 765 766 /** 767 * Retrieves the text (if any) that should appear after the single-use token 768 * in the message delivered to the user via a mechanism that imposes 769 * significant constraints on message size. 770 * 771 * @return The text that should appear after the single-use token in the 772 * message delivered to the user via a mechanism that imposes 773 * significant constraints on message size, or {@code null} if there 774 * should not be any text after the token. 775 */ 776 public String getCompactTextAfterToken() 777 { 778 return compactTextAfterToken; 779 } 780 781 782 783 /** 784 * Retrieves an ordered list of the preferred delivery mechanisms that should 785 * be used to provide the password reset token to the user, optionally paired 786 * with a mechanism-specific recipient ID (e.g., a mobile phone number for SMS 787 * delivery, or an email address for email delivery) that can be used in the 788 * delivery. If this list is non-empty, then the server will use the first 789 * mechanism in the list that the server supports and is available for the 790 * target user, and the server will only consider mechanisms in the provided 791 * list even if the server supports alternate mechanisms that are not 792 * included. If this list is empty, then the server will attempt to select an 793 * appropriate delivery mechanism for the user. 794 * 795 * @return An ordered list of the preferred delivery mechanisms for the 796 * password reset token, or an empty list if none were provided. 797 */ 798 public List<ObjectPair<String,String>> getPreferredDeliveryMechanisms() 799 { 800 return preferredDeliveryMechanisms; 801 } 802 803 804 805 /** 806 * {@inheritDoc} 807 */ 808 @Override() 809 public DeliverPasswordResetTokenExtendedResult process( 810 final LDAPConnection connection, final int depth) 811 throws LDAPException 812 { 813 final ExtendedResult extendedResponse = super.process(connection, depth); 814 return new DeliverPasswordResetTokenExtendedResult(extendedResponse); 815 } 816 817 818 819 /** 820 * {@inheritDoc}. 821 */ 822 @Override() 823 public DeliverPasswordResetTokenExtendedRequest duplicate() 824 { 825 return duplicate(getControls()); 826 } 827 828 829 830 /** 831 * {@inheritDoc}. 832 */ 833 @Override() 834 public DeliverPasswordResetTokenExtendedRequest duplicate( 835 final Control[] controls) 836 { 837 final DeliverPasswordResetTokenExtendedRequest r = 838 new DeliverPasswordResetTokenExtendedRequest(userDN, 839 messageSubject, fullTextBeforeToken, fullTextAfterToken, 840 compactTextBeforeToken, compactTextAfterToken, 841 preferredDeliveryMechanisms, controls); 842 r.setResponseTimeoutMillis(getResponseTimeoutMillis(null)); 843 return r; 844 } 845 846 847 848 /** 849 * {@inheritDoc} 850 */ 851 @Override() 852 public String getExtendedRequestName() 853 { 854 return INFO_EXTENDED_REQUEST_NAME_DELIVER_PW_RESET_TOKEN.get(); 855 } 856 857 858 859 /** 860 * {@inheritDoc} 861 */ 862 @Override() 863 public void toString(final StringBuilder buffer) 864 { 865 buffer.append("DeliverPasswordResetTokenExtendedRequest(userDN='"); 866 buffer.append(userDN); 867 buffer.append('\''); 868 869 if (messageSubject != null) 870 { 871 buffer.append(", messageSubject='"); 872 buffer.append(messageSubject); 873 buffer.append('\''); 874 } 875 876 if (fullTextBeforeToken != null) 877 { 878 buffer.append(", fullTextBeforeToken='"); 879 buffer.append(fullTextBeforeToken); 880 buffer.append('\''); 881 } 882 883 if (fullTextAfterToken != null) 884 { 885 buffer.append(", fullTextAfterToken='"); 886 buffer.append(fullTextAfterToken); 887 buffer.append('\''); 888 } 889 890 if (compactTextBeforeToken != null) 891 { 892 buffer.append(", compactTextBeforeToken='"); 893 buffer.append(compactTextBeforeToken); 894 buffer.append('\''); 895 } 896 897 if (compactTextAfterToken != null) 898 { 899 buffer.append(", compactTextAfterToken='"); 900 buffer.append(compactTextAfterToken); 901 buffer.append('\''); 902 } 903 904 if (preferredDeliveryMechanisms != null) 905 { 906 buffer.append(", preferredDeliveryMechanisms={"); 907 908 final Iterator<ObjectPair<String,String>> iterator = 909 preferredDeliveryMechanisms.iterator(); 910 while (iterator.hasNext()) 911 { 912 final ObjectPair<String,String> p = iterator.next(); 913 buffer.append('\''); 914 buffer.append(p.getFirst()); 915 if (p.getSecond() != null) 916 { 917 buffer.append('('); 918 buffer.append(p.getSecond()); 919 buffer.append(')'); 920 } 921 buffer.append('\''); 922 if (iterator.hasNext()) 923 { 924 buffer.append(','); 925 } 926 } 927 } 928 929 final Control[] controls = getControls(); 930 if (controls.length > 0) 931 { 932 buffer.append(", controls={"); 933 for (int i=0; i < controls.length; i++) 934 { 935 if (i > 0) 936 { 937 buffer.append(", "); 938 } 939 940 buffer.append(controls[i]); 941 } 942 buffer.append('}'); 943 } 944 945 buffer.append(')'); 946 } 947}