浏览代码

Implement Change Password dialog on HelpDesk detail page - part 2 (dialog to set password randomly, clear answers dialog)

Joseph White 7 年之前
父节点
当前提交
c94632b3b6

+ 27 - 8
client/src/helpdesk/helpdesk-detail.component.ts

@@ -24,6 +24,7 @@
 import {Component} from '../component';
 import {Component} from '../component';
 import {IButtonInfo, IHelpDeskService, ISuccessResponse} from '../services/helpdesk.service';
 import {IButtonInfo, IHelpDeskService, ISuccessResponse} from '../services/helpdesk.service';
 import {IScope, ui} from '@types/angular';
 import {IScope, ui} from '@types/angular';
+import {noop} from 'angular';
 import {IActionButtons, IHelpDeskConfigService} from '../services/helpdesk-config.service';
 import {IActionButtons, IHelpDeskConfigService} from '../services/helpdesk-config.service';
 import DialogService from '../ux/ias-dialog.service';
 import DialogService from '../ux/ias-dialog.service';
 import {IPeopleService} from '../services/people.service';
 import {IPeopleService} from '../services/people.service';
@@ -43,7 +44,6 @@ const STATUS_SUCCESS = 'success';
     templateUrl: require('helpdesk/helpdesk-detail.component.html')
     templateUrl: require('helpdesk/helpdesk-detail.component.html')
 })
 })
 export default class HelpDeskDetailComponent {
 export default class HelpDeskDetailComponent {
-    actionButtons: IActionButtons;
     person: any;
     person: any;
     personCard: IPerson;
     personCard: IPerson;
     photosEnabled: boolean;
     photosEnabled: boolean;
@@ -90,9 +90,34 @@ export default class HelpDeskDetailComponent {
                 controller: 'PasswordSuggestionsDialogController as $ctrl',
                 controller: 'PasswordSuggestionsDialogController as $ctrl',
                 templateUrl: passwordSuggestionsDialogTemplateUrl,
                 templateUrl: passwordSuggestionsDialogTemplateUrl,
                 locals: {
                 locals: {
+                    personUsername: this.person.userDisplayName,
                     personUserKey: this.getUserKey(),
                     personUserKey: this.getUserKey(),
                 }
                 }
-            });
+            })
+            .then(() => {
+                let userKey = this.getUserKey();
+
+                this.IasDialogService
+                    .open({
+                        controller: [
+                            '$scope',
+                            'HelpDeskService',
+                            'translateFilter',
+                            function ($scope: IScope,
+                                      helpDeskService: IHelpDeskService,
+                                      translateFilter: (id: string) => string) {
+                                $scope.status = STATUS_WAIT;
+                                $scope.title = translateFilter('Button_ClearResponses');
+                                helpDeskService.clearResponses(userKey).then((data: ISuccessResponse) => {
+                                    // TODO - error dialog?
+                                    $scope.status = STATUS_SUCCESS;
+                                    $scope.text = data.successMessage;
+                                });
+                            }
+                        ],
+                        templateUrl: helpdeskDetailDialogTemplateUrl
+                    });
+            }, noop);
     }
     }
 
 
     clearOtpSecret(): void {
     clearOtpSecret(): void {
@@ -264,12 +289,6 @@ export default class HelpDeskDetailComponent {
             }, (error) => {
             }, (error) => {
                 // TODO: Handle error. NOOP for now will not assign person
                 // TODO: Handle error. NOOP for now will not assign person
             });
             });
-
-        this.configService
-            .getActionButtons()
-            .then((actionButtons: IActionButtons) => {
-                this.actionButtons = actionButtons;
-            });     // TODO: remove this code
     }
     }
 
 
     refresh(): void {
     refresh(): void {

+ 70 - 20
client/src/helpdesk/password-suggestions-dialog.html

@@ -20,34 +20,84 @@
   ~ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   ~ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   -->
   -->
 
 
-<ias-dialog class="password-suggestions-dialog">
-    <div class="ias-dialog-header">
-        <div class="ias-title" ng-bind="'Title_RandomPasswords' | translate"></div>
+<ias-dialog class="password-suggestions-dialog" ng-switch="$ctrl.status">
+
+    <div ng-switch-when="confirm-random">
+        <div class="ias-dialog-header">
+            <div class="ias-title" ng-bind="('Title_ChangePassword' | translate) + ': ' + $ctrl.personUsername"></div>
+        </div>
+        <div class="ias-dialog-body">
+            <p ng-bind="'Display_SetRandomPasswordPrompt' | translate"></p>
+        </div>
+        <div class="ias-actions">
+            <mf-button ng-click="$ctrl.confirmSetRandomPassword()">{{ 'Button_OK' | translate }}</mf-button>
+            <mf-button ng-click="cancel()">{{ 'Button_Cancel' | translate }}</mf-button>
+        </div>
+    </div>
+
+    <div ng-switch-when="type">
+        <div class="ias-dialog-header">
+            <div class="ias-title" ng-bind="('Title_ChangePassword' | translate) + ' - ' + $ctrl.personUsername"></div>
+        </div>
+        <div class="ias-dialog-body">
+            <!--Password list
+            First pw   strength
+            Second pw  checkmark-->
+        </div>
+        <div class="ias-actions">
+            <mf-button ng-click="$ctrl.chooseTypedPassword()">{{ 'Button_ChangePassword' | translate }}</mf-button>
+            <mf-button ng-click="$ctrl.status = 'autogen'"
+                       ng-if="$ctrl.passwordUiMode === 'both'">{{ 'Title_RandomPasswords' | translate }}</mf-button>
+        </div>
     </div>
     </div>
 
 
-    <div class="ias-dialog-body">
-        <p ng-bind="'Display_PasswordGeneration' | translate"></p>
-        <table>
-            <tbody>
-            <tr ng-repeat="i in [0,2,4,6,8,10,12,14,16,18]">
-                <td ng-repeat="j in [i, i+1]">
-                    <div href="#" ng-bind="$ctrl.passwordSuggestions[j]" ng-click="$ctrl.onChoosePassword(j)">
-                    </div>
-                </td>
-            </tr>
-            </tbody>
-        </table>
+    <div ng-switch-when="autogen">
+        <div class="ias-dialog-header">
+            <div class="ias-title" ng-bind="'Title_RandomPasswords' | translate"></div>
+        </div>
+        <div class="ias-dialog-body">
+            <p ng-bind="'Display_PasswordGeneration' | translate"></p>
+            <table>
+                <tbody>
+                <tr ng-repeat="i in [0,2,4,6,8,10,12,14,16,18]">
+                    <td ng-repeat="j in [i, i+1]">
+                        <div ng-bind="$ctrl.passwordSuggestions[j]" ng-click="$ctrl.onChoosePasswordSuggestion(j)">
+                        </div>
+                    </td>
+                </tr>
+                </tbody>
+            </table>
+        </div>
+        <div class="ias-actions">
+            <mf-button ng-click="$ctrl.populatePasswordSuggestions()"
+                       ng-disabled="$ctrl.fetchingRandoms">{{ 'Button_More' | translate }}</mf-button>
+            <mf-button ng-click="cancel()">{{ 'Button_Cancel' | translate }}</mf-button>
+        </div>
     </div>
     </div>
 
 
-    <div class="ias-actions">
-        <mf-button ng-click="$ctrl.onMoreRandomsButtonClick()"
-                   ng-disabled="$ctrl.fetchingRandoms">{{ 'Button_More' | translate }}</mf-button>
-        <mf-button ng-click="close()">{{ 'Button_Cancel' | translate }}</mf-button>
+    <div ng-switch-when="finished">
+        <div class="ias-dialog-header">
+            <div class="ias-title" ng-bind="('Title_ChangePassword' | translate) + ' - ' + $ctrl.personUsername"></div>
+        </div>
+        <div class="ias-dialog-body">
+            <p ng-bind="$ctrl.successMessage"></p>
+            <span ng-bind="'Field_NewPassword' | translate"></span>
+            <mf-button ng-click="$ctrl.togglePasswordMasked()" ng-if="$ctrl.maskPasswords">
+                {{ 'Button_Show' | translate }}
+            </mf-button>
+            <input ng-model="$ctrl.chosenPassword" ng-hide="$ctrl.passwordMasked" readonly type="text">
+        </div>
+        <div class="ias-actions">
+            <mf-button ng-click="cancel()">{{ 'Button_OK' | translate }}</mf-button>
+            <mf-button ng-click="$ctrl.clearAnswers()"
+                       ng-if="$ctrl.clearResponsesSetting==='ask'">{{ 'Button_ClearResponses' | translate }}</mf-button>
+        </div>
     </div>
     </div>
+
     <mf-icon-button class="ias-dialog-close-button"
     <mf-icon-button class="ias-dialog-close-button"
                     icon="close_thick"
                     icon="close_thick"
                     id="close-icon"
                     id="close-icon"
                     ng-attr-title="{{ 'Button_CloseWindow' | translate }}"
                     ng-attr-title="{{ 'Button_CloseWindow' | translate }}"
-                    ng-click="close()">
+                    ng-click="cancel()">
     </mf-icon-button>
     </mf-icon-button>
 </ias-dialog>
 </ias-dialog>

+ 98 - 21
client/src/helpdesk/password-suggestions.controller.ts

@@ -21,47 +21,99 @@
  */
  */
 
 
 
 
-import {IHelpDeskService, IRandomPasswordResponse} from '../services/helpdesk.service';
+import {IHelpDeskService, IRandomPasswordResponse, ISuccessResponse} from '../services/helpdesk.service';
 import {IPromise, IQService} from 'angular';
 import {IPromise, IQService} from 'angular';
+import {IHelpDeskConfigService, PASSWORD_UI_MODES} from '../services/helpdesk-config.service';
+import DialogService from '../ux/ias-dialog.service';
 
 
-let RANDOM_MAPPING_LENGTH = 20;
+const RANDOM_MAPPING_SIZE = 20;
+const STATUS_AUTOGEN = 'autogen';
+const STATUS_CONFIRM_RANDOM = 'confirm-random';
+const STATUS_FINISHED = 'finished';
+const STATUS_TYPE = 'type';
 
 
 require('helpdesk/password-suggestions-dialog.scss');
 require('helpdesk/password-suggestions-dialog.scss');
 
 
 export default class PasswordSuggestionsDialogController {
 export default class PasswordSuggestionsDialogController {
+    chosenPassword: string;
+    clearResponsesSetting: string;
     fetchingRandoms: boolean;
     fetchingRandoms: boolean;
+    maskPasswords: boolean;
+    passwordMasked: boolean;
     passwordSuggestions: string[];
     passwordSuggestions: string[];
+    passwordUiMode: string;
+    status: string;
+    successMessage: string;
+    // this.HelpDeskService.showStrengthMeter;
 
 
-    static $inject = [ '$q', 'HelpDeskService', 'personUserKey' ];
-    constructor(private $q: IQService, private HelpDeskService: IHelpDeskService, private personUserKey: string) {
+    static $inject = [
+        '$q',
+        'ConfigService',
+        'HelpDeskService',
+        'IasDialogService',
+        'personUsername',
+        'personUserKey',
+        'translateFilter'
+    ];
+    constructor(private $q: IQService,
+                private configService: IHelpDeskConfigService,
+                private HelpDeskService: IHelpDeskService,
+                private IasDialogService: DialogService,
+                private personUsername: string,
+                private personUserKey: string,
+                private translateFilter: (id: string) => string) {
         this.passwordSuggestions = Array(20).fill('');
         this.passwordSuggestions = Array(20).fill('');
-        this.fetchRandoms();
+
+        let promise = this.$q.all([
+            this.configService.getClearResponsesSetting(),
+            this.configService.getPasswordUiMode(),
+            this.configService.maskPasswordsEnabled()
+        ]);
+        promise.then((result) => {
+            this.clearResponsesSetting = result[0];
+            this.passwordUiMode = result[1];
+            this.maskPasswords = result[2];
+            this.passwordMasked = this.maskPasswords;   // Set now instead of when we set status to STATUS_FINISHED
+            if (this.passwordUiMode === PASSWORD_UI_MODES.AUTOGEN) {
+                this.status = STATUS_AUTOGEN;
+                this.populatePasswordSuggestions();
+            }
+            else if (this.passwordUiMode === PASSWORD_UI_MODES.RANDOM) {
+                this.status = STATUS_CONFIRM_RANDOM;
+            }
+            else if (this.passwordUiMode === PASSWORD_UI_MODES.BOTH || this.passwordUiMode === PASSWORD_UI_MODES.TYPE) {
+                this.status = STATUS_TYPE;
+            }
+            else {
+                throw new Error('Password type unsupported!');  // TODO: best way to do this?
+            }
+        });
     }
     }
 
 
-    onChoosePassword(index: number) {
-        let password = this.passwordSuggestions[index];
-        // change password
+    chooseTypedPassword() {     // todo: should this be merged with onChoosePasswordSuggestion?
+        this.HelpDeskService.setPassword(this.personUserKey, false, this.chosenPassword)
+            .then((result: ISuccessResponse) => {
+                this.status = STATUS_FINISHED;
+                this.successMessage = result.successMessage;
+            });
     }
     }
 
 
-    onMoreRandomsButtonClick() {
-        this.fetchRandoms();
+    clearAnswers() {
+        this.IasDialogService.close();
     }
     }
 
 
-    fetchRandoms() {
-        this.fetchingRandoms = true;
-        let ordering = this.generateRandomMapping();
-        let promiseChain: IPromise<any> = this.$q.when();
-        ordering.forEach((index: number) => {
-            promiseChain = promiseChain.then(this.passwordSuggestionFactory(index));
-        });
-        promiseChain.then(() => {
-            this.fetchingRandoms = false;
-        });
+    confirmSetRandomPassword() {
+        this.HelpDeskService.setPassword(this.personUserKey, true)
+            .then((result: ISuccessResponse) => {
+                this.chosenPassword = '[' + this.translateFilter('Display_Random') +  ']';
+                this.status = STATUS_FINISHED;
+                this.successMessage = result.successMessage;
+            });
     }
     }
 
 
     generateRandomMapping(): number[] {
     generateRandomMapping(): number[] {
         let map: number[] = [];
         let map: number[] = [];
-        for (let i = 0; i < RANDOM_MAPPING_LENGTH; i++) {
+        for (let i = 0; i < RANDOM_MAPPING_SIZE; i++) {
             map.push(i);
             map.push(i);
         }
         }
         let randomComparatorFunction = () => 0.5 - Math.random();
         let randomComparatorFunction = () => 0.5 - Math.random();
@@ -70,6 +122,15 @@ export default class PasswordSuggestionsDialogController {
         return map;
         return map;
     }
     }
 
 
+    onChoosePasswordSuggestion(index: number) {
+        this.chosenPassword = this.passwordSuggestions[index];
+        this.HelpDeskService.setPassword(this.personUserKey, false, this.chosenPassword)
+            .then((result: ISuccessResponse) => {
+                this.status = STATUS_FINISHED;
+                this.successMessage = result.successMessage;
+            });
+    }
+
     passwordSuggestionFactory(index: number): any {
     passwordSuggestionFactory(index: number): any {
         return () => {
         return () => {
             return this.HelpDeskService.getRandomPassword(this.personUserKey).then(
             return this.HelpDeskService.getRandomPassword(this.personUserKey).then(
@@ -79,4 +140,20 @@ export default class PasswordSuggestionsDialogController {
             );
             );
         };
         };
     }
     }
+
+    populatePasswordSuggestions() {
+        this.fetchingRandoms = true;
+        let ordering = this.generateRandomMapping();
+        let promiseChain: IPromise<any> = this.$q.when();
+        ordering.forEach((index: number) => {
+            promiseChain = promiseChain.then(this.passwordSuggestionFactory(index));
+        });
+        promiseChain.then(() => {
+            this.fetchingRandoms = false;
+        });
+    }
+
+    togglePasswordMasked() {
+        this.passwordMasked = !this.passwordMasked;
+    }
 }
 }

+ 5 - 0
client/src/i18n/translations_en.json

@@ -12,6 +12,7 @@
   "Button_More": "More",
   "Button_More": "More",
   "Button_OK": "OK",
   "Button_OK": "OK",
   "Button_OTP": "OTP",
   "Button_OTP": "OTP",
+  "Button_Show": "Show",
   "Button_SMS": "SMS",
   "Button_SMS": "SMS",
   "Button_Unlock": "Unlock",
   "Button_Unlock": "Unlock",
   "Button_Verifications": "Verifications",
   "Button_Verifications": "Verifications",
@@ -22,18 +23,22 @@
   "Display_HelpdeskOtpValidation": "Instruct the user to load their mobile authentication app and share the current pass code.",
   "Display_HelpdeskOtpValidation": "Instruct the user to load their mobile authentication app and share the current pass code.",
   "Display_PasswordGeneration": "The following passwords have been randomly generated for you.  These passwords are based on real words to make them easier to remember, but have been modified to make them difficult to guess.",
   "Display_PasswordGeneration": "The following passwords have been randomly generated for you.  These passwords are based on real words to make them easier to remember, but have been modified to make them difficult to guess.",
   "Display_PleaseWait": "Loading...",
   "Display_PleaseWait": "Loading...",
+  "Display_Random": "Random",
   "Display_SearchResultsExceeded": "Search results exceeded maximum search size",
   "Display_SearchResultsExceeded": "Search results exceeded maximum search size",
   "Display_SearchResultsNone": "No results",
   "Display_SearchResultsNone": "No results",
+  "Display_SetRandomPasswordPrompt": "Set a new random password for this user?",
   "Display_TokenDestination": "Token Destination",
   "Display_TokenDestination": "Token Destination",
   "Field_DateTime": "Date/Time",
   "Field_DateTime": "Date/Time",
   "Field_Display": "Display",
   "Field_Display": "Display",
   "Field_LdapProfile": "LDAP Profile",
   "Field_LdapProfile": "LDAP Profile",
   "Field_Method": "Method",
   "Field_Method": "Method",
+  "Field_NewPassword": "New Password",
   "Field_Policy": "Policy",
   "Field_Policy": "Policy",
   "Field_Profile": "Profile",
   "Field_Profile": "Profile",
   "Field_Username": "User Name",
   "Field_Username": "User Name",
   "Long_Title_VerificationSend": "Before this user can be selected, the user's identity must be verified.  Please select a verification method.",
   "Long_Title_VerificationSend": "Before this user can be selected, the user's identity must be verified.  Please select a verification method.",
   "Placeholder_Search": "Search",
   "Placeholder_Search": "Search",
+  "Title_ChangePassword": "Change Password",
   "Title_Details": "Details",
   "Title_Details": "Details",
   "Title_DirectReports": "Direct Report(s)",
   "Title_DirectReports": "Direct Report(s)",
   "Title_HelpDesk": "Help Desk",
   "Title_HelpDesk": "Help Desk",

+ 7 - 16
client/src/services/helpdesk-config.service.dev.ts

@@ -26,7 +26,7 @@ import {ConfigBaseService} from './base-config.service.dev';
 import {IConfigService} from './base-config.service';
 import {IConfigService} from './base-config.service';
 import {
 import {
     IActionButtons,
     IActionButtons,
-    IHelpDeskConfigService, IVerificationMap, TOKEN_CHOICE, VERIFICATION_METHOD_LABELS,
+    IHelpDeskConfigService, IVerificationMap, PASSWORD_UI_MODES, TOKEN_CHOICE, VERIFICATION_METHOD_LABELS,
     VERIFICATION_METHOD_NAMES
     VERIFICATION_METHOD_NAMES
 } from './helpdesk-config.service';
 } from './helpdesk-config.service';
 
 
@@ -37,21 +37,8 @@ export default class HelpDeskConfigService extends ConfigBaseService implements
         super($q);
         super($q);
     }
     }
 
 
-    getActionButtons(): IPromise<IActionButtons> {
-        return this.$q.resolve({
-            'Confirm New User Generation': {
-                name: 'Generate a New User',
-                description: 'Clones the current user'
-            },
-            'Confirm User Merge': {
-                name: 'Merge Two Users',
-                description: 'Merges the current user with another user'
-            }
-        });
-    }
-
-    getPasswordUiMode(): IPromise<string> {
-        return this.$q.resolve('both');
+    getClearResponsesSetting(): IPromise<string> {
+        return this.$q.resolve('ask');
     }
     }
 
 
     getColumnConfig(): IPromise<any> {
     getColumnConfig(): IPromise<any> {
@@ -65,6 +52,10 @@ export default class HelpDeskConfigService extends ConfigBaseService implements
         });
         });
     }
     }
 
 
+    getPasswordUiMode(): IPromise<string> {
+        return this.$q.resolve(PASSWORD_UI_MODES.RANDOM);
+    }
+
     getTokenSendMethod(): IPromise<string> {
     getTokenSendMethod(): IPromise<string> {
         return this.$q.resolve(TOKEN_CHOICE);
         return this.$q.resolve(TOKEN_CHOICE);
     }
     }

+ 12 - 4
client/src/services/helpdesk-config.service.ts

@@ -26,7 +26,7 @@ import IPwmService from './pwm.service';
 import PwmService from './pwm.service';
 import PwmService from './pwm.service';
 import {ConfigBaseService, IConfigService} from './base-config.service';
 import {ConfigBaseService, IConfigService} from './base-config.service';
 
 
-const ACTION_BUTTONS_CONFIG = 'actions';
+const CLEAR_RESPONSES_CONFIG = 'helpdesk_setting_clearResponses';
 const COLUMN_CONFIG = 'helpdesk_search_columns';
 const COLUMN_CONFIG = 'helpdesk_search_columns';
 const MASK_PASSWORDS_CONFIG = 'helpdesk_setting_maskPasswords';
 const MASK_PASSWORDS_CONFIG = 'helpdesk_setting_maskPasswords';
 const PASSWORD_UI_MODE_CONFIG = 'helpdesk_setting_PwUiMode';
 const PASSWORD_UI_MODE_CONFIG = 'helpdesk_setting_PwUiMode';
@@ -38,6 +38,14 @@ const VERIFICATION_FORM_CONFIG = 'verificationForm';
 const VERIFICATION_METHODS_CONFIG = 'verificationMethods';
 const VERIFICATION_METHODS_CONFIG = 'verificationMethods';
 export const TOKEN_CHOICE = 'CHOICE_SMS_EMAIL';
 export const TOKEN_CHOICE = 'CHOICE_SMS_EMAIL';
 
 
+export const PASSWORD_UI_MODES = {
+    NONE: 'NONE',
+    AUTOGEN: 'AUTOGEN',
+    RANDOM: 'RANDOM',
+    TYPE: 'TYPE',
+    BOTH: 'BOTH'
+};
+
 export const VERIFICATION_METHOD_NAMES = {
 export const VERIFICATION_METHOD_NAMES = {
     ATTRIBUTES: 'ATTRIBUTES',
     ATTRIBUTES: 'ATTRIBUTES',
     EMAIL: 'EMAIL',
     EMAIL: 'EMAIL',
@@ -64,7 +72,7 @@ interface IVerificationResponse {
 export type IVerificationMap = {name: string, label: string}[];
 export type IVerificationMap = {name: string, label: string}[];
 
 
 export interface IHelpDeskConfigService extends IConfigService {
 export interface IHelpDeskConfigService extends IConfigService {
-    getActionButtons(): IPromise<IActionButtons>;
+    getClearResponsesSetting(): IPromise<string>;
     getPasswordUiMode(): IPromise<string>;
     getPasswordUiMode(): IPromise<string>;
     getTokenSendMethod(): IPromise<string>;
     getTokenSendMethod(): IPromise<string>;
     getVerificationAttributes(): IPromise<IVerificationMap>;
     getVerificationAttributes(): IPromise<IVerificationMap>;
@@ -80,8 +88,8 @@ export default class HelpDeskConfigService extends ConfigBaseService implements
         super($http, $log, $q, pwmService);
         super($http, $log, $q, pwmService);
     }
     }
 
 
-    getActionButtons(): IPromise<IActionButtons> {
-        return this.getValue(ACTION_BUTTONS_CONFIG);
+    getClearResponsesSetting(): IPromise<string> {
+        return this.getValue(CLEAR_RESPONSES_CONFIG);
     }
     }
 
 
     getColumnConfig(): IPromise<any> {
     getColumnConfig(): IPromise<any> {

+ 10 - 1
client/src/services/helpdesk.service.dev.ts

@@ -26,7 +26,7 @@ import {
 } from './helpdesk.service';
 } from './helpdesk.service';
 import {IPromise, IQService, ITimeoutService, IWindowService} from 'angular';
 import {IPromise, IQService, ITimeoutService, IWindowService} from 'angular';
 
 
-const SIMULATED_RESPONSE_TIME = 300;
+const SIMULATED_RESPONSE_TIME = 30;
 
 
 export default class HelpDeskService implements IHelpDeskService {
 export default class HelpDeskService implements IHelpDeskService {
     PWM_GLOBAL: any;
     PWM_GLOBAL: any;
@@ -446,6 +446,15 @@ export default class HelpDeskService implements IHelpDeskService {
         return this.simulateResponse({ destination: 'bcarrolj@paypal.com' });
         return this.simulateResponse({ destination: 'bcarrolj@paypal.com' });
     }
     }
 
 
+    setPassword(userKey: string, random: boolean, password?: string): IPromise<ISuccessResponse> {
+        if (random) {
+            return this.simulateResponse({ successMessage: 'Random password successfully set!' });
+        }
+        else {
+            return this.simulateResponse({ successMessage: 'Password successfully set!' });
+        }
+    }
+
     private simulateResponse<T>(data: T): IPromise<T> {
     private simulateResponse<T>(data: T): IPromise<T> {
         let self = this;
         let self = this;
 
 

+ 18 - 0
client/src/services/helpdesk.service.ts

@@ -45,6 +45,7 @@ export interface IHelpDeskService {
     getRandomPassword(userKey: string): IPromise<IRandomPasswordResponse>;
     getRandomPassword(userKey: string): IPromise<IRandomPasswordResponse>;
     getRecentVerifications(): IPromise<IRecentVerifications>;
     getRecentVerifications(): IPromise<IRecentVerifications>;
     sendVerificationToken(userKey: string, choice: string): IPromise<IVerificationTokenResponse>;
     sendVerificationToken(userKey: string, choice: string): IPromise<IVerificationTokenResponse>;
+    setPassword(userKey: string, random: boolean, password?: string): IPromise<ISuccessResponse>;
     unlockIntruder(userKey: string): IPromise<ISuccessResponse>;
     unlockIntruder(userKey: string): IPromise<ISuccessResponse>;
     validateVerificationData(userKey: string, formData: any, tokenData: any): IPromise<IVerificationStatus>;
     validateVerificationData(userKey: string, formData: any, tokenData: any): IPromise<IVerificationStatus>;
     showStrengthMeter: boolean;
     showStrengthMeter: boolean;
@@ -215,6 +216,23 @@ export default class HelpDeskService implements IHelpDeskService {
             });
             });
     }
     }
 
 
+    setPassword(userKey: string, random: boolean, password?: string): IPromise<ISuccessResponse> {
+        let url: string = this.pwmService.getServerUrl('setPassword');
+        let data: any = { username: userKey };
+        if (random) {
+            data.random = true;
+        }
+        else {
+            data.password = password;
+        }
+
+        return this.pwmService
+            .httpRequest(url, { data: data })
+            .then((result: ISuccessResponse) => {
+                return this.$q.resolve(result);
+            });
+    }
+
     unlockIntruder(userKey: string): IPromise<ISuccessResponse> {
     unlockIntruder(userKey: string): IPromise<ISuccessResponse> {
         let url: string = this.pwmService.getServerUrl('unlockIntruder');
         let url: string = this.pwmService.getServerUrl('unlockIntruder');
         url += `&userKey=${userKey}`;
         url += `&userKey=${userKey}`;