Wiki source code of Reset your password
Last modified by Ecaterina Valica on 2016/11/17 15:21
Show last authors
author | version | line-number | content |
---|---|---|---|
1 | {{velocity output="false"}} | ||
2 | #** | ||
3 | This page completes the password reset procedure. It works according to the next algorithm: | ||
4 | 1. Verify that the correct verification URL is entered, by checking the 'u' and 'v' request parameters against the existing ResetPasswordRequest objects | ||
5 | 2. Display a form requesting the new password | ||
6 | 3. When receiving the new password via form submission, update the user object with the new password, and remove the ResetPasswordRequest object | ||
7 | |||
8 | URL parameters: | ||
9 | |||
10 | u = user account in the verification URL | ||
11 | v = random verification string | ||
12 | p = the new password | ||
13 | p2 = the new password (for misspelling check) | ||
14 | |||
15 | !!!!! IMPORTANT !!!!! | ||
16 | |||
17 | This document requires programming rights, so always make sure | ||
18 | it is saved by a user with programming rights, and that | ||
19 | it is secured against unprivileged editing. | ||
20 | |||
21 | *### | ||
22 | ## | ||
23 | ## | ||
24 | ## The name of the class used for storing password reset verification data. | ||
25 | #set ($verifClass = 'XWiki.ResetPasswordRequestClass') | ||
26 | ## | ||
27 | ## START MACROS | ||
28 | ## | ||
29 | #** | ||
30 | * Encrypt a string to get the value that would be stored inside a PasswordProperty field. | ||
31 | * It is used to check if the unencrypted parameter from the URL is the value stored in the | ||
32 | * ResetPasswordRequest object. | ||
33 | * @param value The plaintext value to encrypt. | ||
34 | * @param storedValue The current value stored in the ResetPasswordRequest object. | ||
35 | * @param result The encrypted output. | ||
36 | *# | ||
37 | #macro(encrypt $value $storedValue $result) | ||
38 | #set ($encryptedValue = $xwiki.getClass($verifClass).getXWikiClass().get('verification').getEquivalentPassword($storedValue, $value)) | ||
39 | #setVariable("$result", $encryptedValue) | ||
40 | #end | ||
41 | ## | ||
42 | ## | ||
43 | #** | ||
44 | * Verify that the request parameters are valid. | ||
45 | * @param userName The user name (full document name) received in the URL. | ||
46 | * @param validationString The unencrypted key that is stored in the ResetPasswordRequestClass object. | ||
47 | * @param result A boolean where the validation result is returned. True if the request is valid, false otherwise. | ||
48 | *# | ||
49 | #macro(verifyRequest $userName $validationString $isValid) | ||
50 | #set ($isValid = false) | ||
51 | #if ($validationString != '' && $userName != '') | ||
52 | #set ($storedValidationString = $!xwiki.getDocumentAsAuthor($userName).getObject($verifClass).getValue('verification')) | ||
53 | #encrypt($validationString, $storedValidationString, $encryptedValidationString) | ||
54 | #if ($storedValidationString == $encryptedValidationString) | ||
55 | #set ($isValid = true) | ||
56 | #end | ||
57 | #end | ||
58 | #end | ||
59 | ## | ||
60 | ## | ||
61 | #** | ||
62 | * Displays the password reset form. | ||
63 | * @param message An optional message to display, for example if the sent password is empty. | ||
64 | * @param u The user account (full document name), which needs to be preserved. | ||
65 | * @param v The validation string, which will be checked again upon receiving the form. | ||
66 | *### | ||
67 | #macro(displayForm $message $userName $validationString) | ||
68 | #if ($message != '') | ||
69 | {{warning}}$message{{/warning}} | ||
70 | #end | ||
71 | |||
72 | {{html}} | ||
73 | <form action="$doc.getURL()" method="post" class="xform third" onsubmit="if($('p').value == '') {alert('$services.localization.render("xe.admin.passwordReset.step2.error.emptyPassword")'); return false;} else if($('p').value != $('p2').value) {alert('$services.localization.render("xe.admin.passwordReset.step2.error.verificationMismatch")'); return false; }"> | ||
74 | <div class="hidden"> | ||
75 | <input type="hidden" name="form_token" value="$!{services.csrf.getToken()}" /> | ||
76 | <input type="hidden" name="u" value="$!escapetool.xml($userName)"/> | ||
77 | <input type="hidden" name="v" value="$!escapetool.xml($validationString)"/> | ||
78 | </div> | ||
79 | <dl> | ||
80 | <dt><label for="p">$services.localization.render('xe.admin.passwordReset.step2.newPassword.label')</label></dt> | ||
81 | <dd><input id="p" type="password" name="p" value="" size="20"/></dd> | ||
82 | <dt><label for="p2">$services.localization.render('xe.admin.passwordReset.step2.newPasswordVerification.label')</label></dt> | ||
83 | <dd><input id="p2" type="password" value="" name="p2" size="20"/></dd> | ||
84 | </dl> | ||
85 | <div class="buttons"> | ||
86 | <span class="buttonwrapper"><input type="submit" value="$services.localization.render('xe.admin.passwordReset.step2.submit')" class="button"/></span> | ||
87 | </div> | ||
88 | </form> | ||
89 | {{/html}} | ||
90 | |||
91 | #end | ||
92 | ## | ||
93 | ## END MACROS | ||
94 | ## | ||
95 | ## | ||
96 | #set ($userName = "$!request.u") | ||
97 | #set ($validationString = "$!request.v") | ||
98 | #set ($password = "$!request.p") | ||
99 | #set ($password2 = "$!request.p2") | ||
100 | #verifyRequest($userName $validationString $isValid) | ||
101 | {{/velocity}} | ||
102 | |||
103 | {{velocity}} | ||
104 | ## | ||
105 | ## | ||
106 | ## First, check if the page has programming rights, as nothing works otherwise | ||
107 | #if ($xwiki.hasProgrammingRights()) | ||
108 | #if ($isValid) | ||
109 | #set ($vuserDoc = $xwiki.getDocumentAsAuthor($userName)) | ||
110 | #if ($request.getParameterMap().containsKey('p'))## Second step, set the user password | ||
111 | #if($password == '') | ||
112 | #displayForm($services.localization.render('xe.admin.passwordReset.step2.error.emptyPassword') $userName $validationString) | ||
113 | #elseif($password != $password2) | ||
114 | #displayForm($services.localization.render('xe.admin.passwordReset.step2.error.verificationMismatch') $userName $validationString) | ||
115 | #else | ||
116 | $vuserDoc.getObject('XWiki.XWikiUsers').set('password', $password) | ||
117 | #set($discard = $vuserDoc.removeObjects($verifClass)) | ||
118 | #set ($discard = $vuserDoc.saveAsAuthor($services.localization.render('xe.admin.passwordReset.step2.versionComment.passwordReset'), true)) | ||
119 | {{info}}{{translation key="xe.admin.passwordReset.step2.success"/}} [[{{translation key="xe.admin.passwordReset.step2.login"/}}>>path:$xwiki.getURL('XWiki.XWikiLogin', 'login')]]{{/info}} | ||
120 | |||
121 | #end | ||
122 | #else## First step, request the user password | ||
123 | ## The user might not complete this step, and leave the URL in the (public) browser's | ||
124 | ## history. Prevent reusing the URL by invalidating the initial verification URL and only | ||
125 | ## post the new string in the hidden form data. | ||
126 | #set ($validationString = $util.generateRandomString(30)) | ||
127 | #set ($discard = $vuserDoc.getObject($verifClass).set('verification', $validationString)) | ||
128 | #set ($discard = $vuserDoc.saveAsAuthor($services.localization.render('xe.admin.passwordReset.step2.versionComment.changeValidationKey'), true)) | ||
129 | #displayForm('' $userName $validationString) | ||
130 | #end | ||
131 | #else | ||
132 | |||
133 | {{error}}{{translation key="xe.admin.passwordReset.step2.error.wrongParameters"/}} [[{{translation key="xe.admin.passwordReset.step2.backToStep1"/}}>>ResetPassword]]{{/error}} | ||
134 | |||
135 | #end | ||
136 | ## | ||
137 | ## Clear private variables, so that they cannot be accessed from the rest of the page (comments, panels...) | ||
138 | #set ($validationString = '') | ||
139 | #set ($password = '') | ||
140 | #set ($password2 = '') | ||
141 | ## | ||
142 | ## | ||
143 | #else## No programming rights, warn and exit | ||
144 | |||
145 | {{error}}{{translation key="xe.admin.passwordReset.step2.error.noProgrammingRights"/}}{{/error}} | ||
146 | |||
147 | #end | ||
148 | {{/velocity}} |