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