Adds functionality for user to change their password when they are logged into the site.
parent
89c5917ed7
commit
b8de3f2d0b
|
@ -26,10 +26,12 @@ import { Account } from '@account/models/account.model';
|
|||
import { environment } from '../../../environments/environment';
|
||||
import { MembershipType } from '@account/models/membership.model';
|
||||
import { handleError } from '@account/app/app.service';
|
||||
import { AbstractControl } from '@angular/forms';
|
||||
|
||||
|
||||
// URLs for the http requests
|
||||
const ACCOUNT_URL = '/api/account';
|
||||
const CHANGE_PASSWORD_URL = '/api/password-change';
|
||||
const MEMBERSHIP_URL = '/api/memberships';
|
||||
|
||||
|
||||
|
@ -80,4 +82,9 @@ export class ProfileService {
|
|||
deleteAccount() {
|
||||
return this.http.delete(ACCOUNT_URL);
|
||||
}
|
||||
|
||||
changePassword(passwordControl: AbstractControl) {
|
||||
const codedPassword = btoa(passwordControl.value);
|
||||
return this.http.put(CHANGE_PASSWORD_URL, {password: codedPassword});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,6 @@
|
|||
</mat-card-content>
|
||||
<mat-card-actions>
|
||||
<a mat-button>CHANGE EMAIL ADDRESS</a>
|
||||
<a mat-button>CHANGE PASSWORD</a>
|
||||
<a mat-button [href]="changePasswordUrl">CHANGE PASSWORD</a>
|
||||
</mat-card-actions>
|
||||
</mat-card>
|
||||
|
|
|
@ -21,6 +21,7 @@ import { Component, Input } from '@angular/core';
|
|||
import { faAddressCard, IconDefinition } from '@fortawesome/free-solid-svg-icons';
|
||||
|
||||
import { Account } from '@account/models/account.model';
|
||||
import { environment } from '@account/environments/environment';
|
||||
|
||||
@Component({
|
||||
selector: 'account-login-edit',
|
||||
|
@ -30,6 +31,7 @@ import { Account } from '@account/models/account.model';
|
|||
export class LoginComponent {
|
||||
@Input() account: Account;
|
||||
public loginIcon: IconDefinition = faAddressCard;
|
||||
public changePasswordUrl = environment.mycroftUrls.account + '/password-change';
|
||||
|
||||
constructor() { }
|
||||
}
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
<mat-card>
|
||||
<mat-card-header>
|
||||
<fa-icon mat-card-avatar [icon]="changePasswordIcon"></fa-icon>
|
||||
<mat-card-title>Change your password</mat-card-title>
|
||||
</mat-card-header>
|
||||
<mat-card-content>
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>New Password</mat-label>
|
||||
<input matInput required [type]="showPassword ? 'text' : 'password'" [formControl]="passwordControl">
|
||||
<mat-error *ngIf="passwordControl.hasError('required')">
|
||||
Password is required
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
<button mat-icon-button (click)="showHidePassword()">
|
||||
<fa-icon [icon]="showPassword ? showIcon : hideIcon"></fa-icon>
|
||||
</button>
|
||||
</mat-card-content>
|
||||
<mat-card-actions>
|
||||
<button
|
||||
mat-button
|
||||
id="submit-button"
|
||||
[disabled]="passwordControl.invalid"
|
||||
(click)="onChangePassword()"
|
||||
>
|
||||
SUBMIT
|
||||
</button>
|
||||
<button mat-button id="cancel-button" (click)="onCancel()">CANCEL</button>
|
||||
</mat-card-actions>
|
||||
</mat-card>
|
|
@ -0,0 +1,53 @@
|
|||
// *****************************************************************************
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
//
|
||||
// Copyright (c) Mycroft AI Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
||||
// this file except in compliance with the License. You may obtain a copy of the
|
||||
// License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
// MERCHANTABLITY OR NON-INFRINGEMENT.
|
||||
//
|
||||
// See the Apache Version 2.0 License for specific language governing permissions
|
||||
// and limitations under the License.
|
||||
// *****************************************************************************
|
||||
|
||||
@use "@angular/material" as mat;
|
||||
@use "components/buttons" as buttons;
|
||||
@use "components/cards" as cards;
|
||||
@use 'mycroft-theme' as theme;
|
||||
|
||||
mat-card {
|
||||
@include cards.selene-card;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
margin-top: 48px;
|
||||
|
||||
mat-card-content {
|
||||
padding: 16px;
|
||||
|
||||
button {
|
||||
margin-top: -8px;
|
||||
fa-icon {
|
||||
font-size: 20px;
|
||||
color: mat.get-color-from-palette(theme.$mycroft-primary, 500);
|
||||
margin-left: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
mat-form-field {
|
||||
width: 240px;
|
||||
}
|
||||
}
|
||||
|
||||
mat-card-actions {
|
||||
#cancel-button {
|
||||
background-color: white;
|
||||
color: mat.get-color-from-palette(theme.$mycroft-accent, 800);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
/*! *****************************************************************************
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
|
||||
Copyright (c) Mycroft AI Inc. All rights reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
||||
this file except in compliance with the License. You may obtain a copy of the
|
||||
License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
MERCHANTABLITY OR NON-INFRINGEMENT.
|
||||
|
||||
See the Apache Version 2.0 License for specific language governing permissions
|
||||
and limitations under the License.
|
||||
***************************************************************************** */
|
||||
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { UntypedFormControl, Validators } from '@angular/forms';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { MatSnackBar, MatSnackBarConfig } from '@angular/material/snack-bar';
|
||||
|
||||
import {faEye, faEyeSlash, faUserSecret, IconDefinition } from '@fortawesome/free-solid-svg-icons';
|
||||
|
||||
import { ProfileService } from '@account/http/profile.service';
|
||||
import { SnackbarComponent } from 'shared';
|
||||
|
||||
const fiveSeconds = 5000;
|
||||
|
||||
@Component({
|
||||
selector: 'account-change-password',
|
||||
templateUrl: './change-password.component.html',
|
||||
styleUrls: ['./change-password.component.scss']
|
||||
})
|
||||
export class ChangePasswordComponent implements OnInit {
|
||||
public changePasswordIcon: IconDefinition = faUserSecret;
|
||||
public hideIcon: IconDefinition = faEyeSlash;
|
||||
public passwordControl = new UntypedFormControl(null, [Validators.required]);
|
||||
public showIcon: IconDefinition = faEye;
|
||||
public showPassword = false;
|
||||
|
||||
constructor(
|
||||
private route: ActivatedRoute,
|
||||
private profileService: ProfileService,
|
||||
private snackbar: MatSnackBar,
|
||||
private dialog: MatDialog,
|
||||
private router: Router
|
||||
) {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
}
|
||||
|
||||
onChangePassword() {
|
||||
this.profileService.changePassword(this.passwordControl).subscribe({
|
||||
next: () => { this.openSuccessSnackbar(); },
|
||||
error: () => { this.openErrorSnackbar(); }
|
||||
});
|
||||
}
|
||||
|
||||
openErrorSnackbar() {
|
||||
const config = new MatSnackBarConfig();
|
||||
config.data = {type: 'error', message: 'An error occurred changing the password'};
|
||||
this.snackbar.openFromComponent(SnackbarComponent, config);
|
||||
}
|
||||
|
||||
openSuccessSnackbar() {
|
||||
const config = new MatSnackBarConfig();
|
||||
config.duration = fiveSeconds;
|
||||
config.data = {type: 'success', message: 'Password successfully changed'};
|
||||
const successSnackbar = this.snackbar.openFromComponent(SnackbarComponent, config);
|
||||
successSnackbar.afterDismissed().subscribe(
|
||||
() => { this.router.navigate(['/profile']); }
|
||||
);
|
||||
}
|
||||
|
||||
onCancel() {
|
||||
this.router.navigate(['/profile']);
|
||||
}
|
||||
|
||||
showHidePassword() {
|
||||
this.showPassword = !this.showPassword;
|
||||
}
|
||||
}
|
|
@ -19,10 +19,11 @@ and limitations under the License.
|
|||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
|
||||
import { AccountResolverService } from '../../core/guards/account-resolver.service';
|
||||
import { MembershipResolverService } from '../../core/guards/membership-resolver.service';
|
||||
import { AccountResolverService } from '@account/app/core/guards/account-resolver.service';
|
||||
import { MembershipResolverService } from '@account/app/core/guards/membership-resolver.service';
|
||||
import { EditComponent } from './pages/edit/edit.component';
|
||||
import { NewComponent } from './pages/new/new.component';
|
||||
import { ChangePasswordComponent } from '@account/app/modules/profile/pages/change-password/change-password.component';
|
||||
|
||||
const profileRoutes: Routes = [
|
||||
{
|
||||
|
@ -39,6 +40,10 @@ const profileRoutes: Routes = [
|
|||
account: AccountResolverService,
|
||||
membershipTypes: MembershipResolverService
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'password-change',
|
||||
component: ChangePasswordComponent
|
||||
}
|
||||
];
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@ import { FontAwesomeModule } from '@fortawesome/angular-fontawesome';
|
|||
import { NgxStripeModule } from 'ngx-stripe';
|
||||
|
||||
import { AgreementsComponent } from './components/cards/agreements/agreements.component';
|
||||
import { ChangePasswordComponent } from './pages/change-password/change-password.component';
|
||||
import { DeleteComponent } from './components/cards/delete/delete.component';
|
||||
import { EditComponent } from './pages/edit/edit.component';
|
||||
import { environment} from '../../../environments/environment';
|
||||
|
@ -56,6 +57,7 @@ import { MembershipStepComponent } from './components/views/membership-step/memb
|
|||
declarations: [
|
||||
// Profile view and edit
|
||||
AgreementsComponent,
|
||||
ChangePasswordComponent,
|
||||
DeleteComponent,
|
||||
EditComponent,
|
||||
LoginComponent,
|
||||
|
|
Loading…
Reference in New Issue