Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
mgr/dashboard: Allow users to change their password on the UI
Fixes: https://tracker.ceph.com/issues/40248 Signed-off-by: Volker Theile <vtheile@suse.com>
- Loading branch information
Showing
21 changed files
with
447 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
110 changes: 110 additions & 0 deletions
110
...dashboard/frontend/src/app/core/auth/user-password-form/user-password-form.component.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
<div class="col-sm-12 col-lg-6"> | ||
<form #frm="ngForm" | ||
[formGroup]="userForm" | ||
novalidate> | ||
<div class="card"> | ||
<div i18n="form title|Example: Create Pool@@formTitle" | ||
class="card-header">{{ action | titlecase }} {{ resource | upperFirst }}</div> | ||
|
||
<div class="card-body"> | ||
<!-- Old password --> | ||
<div class="form-group row"> | ||
<label class="col-form-label col-sm-3" | ||
for="oldpassword"> | ||
<ng-container i18n>Old password</ng-container> | ||
<span class="required"></span> | ||
</label> | ||
<div class="col-sm-9"> | ||
<div class="input-group"> | ||
<input class="form-control" | ||
type="password" | ||
placeholder="Old password..." | ||
id="oldpassword" | ||
formControlName="oldpassword" | ||
autocomplete="off" | ||
autofocus> | ||
<span class="input-group-append"> | ||
<button class="btn btn-light" | ||
cdPasswordButton="oldpassword"> | ||
</button> | ||
</span> | ||
</div> | ||
<span class="invalid-feedback" | ||
*ngIf="userForm.showError('oldpassword', frm, 'required')" | ||
i18n>This field is required.</span> | ||
</div> | ||
</div> | ||
|
||
<!-- New password --> | ||
<div class="form-group row"> | ||
<label class="col-form-label col-sm-3" | ||
for="newpassword"> | ||
<ng-container i18n>New password</ng-container> | ||
<span class="required"></span> | ||
</label> | ||
<div class="col-sm-9"> | ||
<div class="input-group"> | ||
<input class="form-control" | ||
type="password" | ||
placeholder="Password..." | ||
id="newpassword" | ||
autocomplete="new-password" | ||
formControlName="newpassword"> | ||
<span class="input-group-append"> | ||
<button class="btn btn-light" | ||
cdPasswordButton="newpassword"> | ||
</button> | ||
</span> | ||
</div> | ||
<span class="invalid-feedback" | ||
*ngIf="userForm.showError('newpassword', frm, 'required')" | ||
i18n>This field is required.</span> | ||
<span class="invalid-feedback" | ||
*ngIf="userForm.showError('newpassword', frm, 'notmatch')" | ||
i18n>The old and new passwords must be different.</span> | ||
</div> | ||
</div> | ||
|
||
<!-- Confirm new password --> | ||
<div class="form-group row"> | ||
<label class="col-form-label col-sm-3" | ||
for="confirmnewpassword"> | ||
<ng-container i18n>Confirm new password</ng-container> | ||
<span class="required"></span> | ||
</label> | ||
<div class="col-sm-9"> | ||
<div class="input-group"> | ||
<input class="form-control" | ||
type="password" | ||
autocomplete="off" | ||
placeholder="Confirm new password..." | ||
id="confirmnewpassword" | ||
formControlName="confirmnewpassword"> | ||
<span class="input-group-append"> | ||
<button class="btn btn-light" | ||
cdPasswordButton="confirmnewpassword"> | ||
</button> | ||
</span> | ||
</div> | ||
<span class="invalid-feedback" | ||
*ngIf="userForm.showError('confirmnewpassword', frm, 'required')" | ||
i18n>This field is required.</span> | ||
<span class="invalid-feedback" | ||
*ngIf="userForm.showError('confirmnewpassword', frm, 'match')" | ||
i18n>Password confirmation doesn't match the new password.</span> | ||
</div> | ||
</div> | ||
</div> | ||
|
||
<div class="card-footer"> | ||
<div class="button-group text-right"> | ||
<cd-submit-button (submitAction)="onSubmit()" | ||
[form]="userForm" | ||
i18n="form action button|Example: Create Pool@@formActionButton"> | ||
{{ action | titlecase }} {{ resource | upperFirst }} | ||
</cd-submit-button> | ||
</div> | ||
</div> | ||
</div> | ||
</form> | ||
</div> |
Empty file.
85 changes: 85 additions & 0 deletions
85
...hboard/frontend/src/app/core/auth/user-password-form/user-password-form.component.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing'; | ||
import { ComponentFixture, TestBed } from '@angular/core/testing'; | ||
import { ReactiveFormsModule } from '@angular/forms'; | ||
import { Router } from '@angular/router'; | ||
import { RouterTestingModule } from '@angular/router/testing'; | ||
|
||
import { ToastrModule } from 'ngx-toastr'; | ||
|
||
import { configureTestBed, FormHelper, i18nProviders } from '../../../../testing/unit-test-helper'; | ||
import { ComponentsModule } from '../../../shared/components/components.module'; | ||
import { CdFormGroup } from '../../../shared/forms/cd-form-group'; | ||
import { AuthStorageService } from '../../../shared/services/auth-storage.service'; | ||
import { SharedModule } from '../../../shared/shared.module'; | ||
import { UserPasswordFormComponent } from './user-password-form.component'; | ||
|
||
describe('UserPasswordFormComponent', () => { | ||
let component: UserPasswordFormComponent; | ||
let fixture: ComponentFixture<UserPasswordFormComponent>; | ||
let form: CdFormGroup; | ||
let formHelper: FormHelper; | ||
let httpTesting: HttpTestingController; | ||
let router: Router; | ||
let authStorageService: AuthStorageService; | ||
|
||
configureTestBed( | ||
{ | ||
imports: [ | ||
HttpClientTestingModule, | ||
RouterTestingModule, | ||
ReactiveFormsModule, | ||
ComponentsModule, | ||
ToastrModule.forRoot(), | ||
SharedModule | ||
], | ||
declarations: [UserPasswordFormComponent], | ||
providers: i18nProviders | ||
}, | ||
true | ||
); | ||
|
||
beforeEach(() => { | ||
fixture = TestBed.createComponent(UserPasswordFormComponent); | ||
component = fixture.componentInstance; | ||
form = component.userForm; | ||
httpTesting = TestBed.get(HttpTestingController); | ||
router = TestBed.get(Router); | ||
authStorageService = TestBed.get(AuthStorageService); | ||
spyOn(router, 'navigate'); | ||
fixture.detectChanges(); | ||
formHelper = new FormHelper(form); | ||
}); | ||
|
||
it('should create', () => { | ||
expect(component).toBeTruthy(); | ||
}); | ||
|
||
it('should validate old password required', () => { | ||
formHelper.expectErrorChange('oldpassword', '', 'required'); | ||
formHelper.expectValidChange('oldpassword', 'foo'); | ||
}); | ||
|
||
it('should validate password match', () => { | ||
formHelper.setValue('newpassword', 'aaa'); | ||
formHelper.expectErrorChange('confirmnewpassword', 'bbb', 'match'); | ||
formHelper.expectValidChange('confirmnewpassword', 'aaa'); | ||
}); | ||
|
||
it('should submit', () => { | ||
spyOn(authStorageService, 'getUsername').and.returnValue('xyz'); | ||
formHelper.setMultipleValues({ | ||
oldpassword: 'foo', | ||
newpassword: 'bar' | ||
}); | ||
formHelper.setValue('confirmnewpassword', 'bar', true); | ||
component.onSubmit(); | ||
const request = httpTesting.expectOne('api/user/xyz/change_password'); | ||
expect(request.request.method).toBe('POST'); | ||
expect(request.request.body).toEqual({ | ||
old_password: 'foo', | ||
new_password: 'bar' | ||
}); | ||
request.flush({}); | ||
expect(router.navigate).toHaveBeenCalledWith(['/logout']); | ||
}); | ||
}); |
Oops, something went wrong.