Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Settings component #1062

Merged
merged 5 commits into from
Nov 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions ui/src/app/account/account.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ import { CommonModule } from '@angular/common'
import { LoginComponent } from './login/login.component'
import { RouterModule } from '@angular/router'
import { ReactiveFormsModule } from '@angular/forms'
import { routes } from './account.route';
import { routes } from './account.route'
import { PasswordResetInitComponent } from './password/password-reset-init.component'
import { SettingsComponent } from './settings/settings.component'
import { SharedModule } from '../shared/shared.module'

@NgModule({
declarations: [LoginComponent, PasswordResetInitComponent],
imports: [CommonModule, ReactiveFormsModule, RouterModule.forChild(routes)],
declarations: [LoginComponent, PasswordResetInitComponent, SettingsComponent],
imports: [SharedModule, CommonModule, ReactiveFormsModule, RouterModule.forChild(routes)],
})
export class AccountModule {}
11 changes: 11 additions & 0 deletions ui/src/app/account/account.route.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { Routes } from '@angular/router'
import { LoginComponent } from './login/login.component'
import { PasswordResetInitComponent } from './password/password-reset-init.component'
import { SettingsComponent } from './settings/settings.component'
import { AuthGuard } from './auth.guard'

export const routes: Routes = [
{
Expand All @@ -15,4 +17,13 @@ export const routes: Routes = [
pageTitle: 'global.menu.account.password.string',
},
},
{
path: 'settings',
component: SettingsComponent,
data: {
authorities: ['ROLE_USER'],
pageTitle: 'global.menu.account.settings.string',
},
canActivate: [AuthGuard],
},
]
2 changes: 0 additions & 2 deletions ui/src/app/account/auth.guard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@ export const AuthGuard = (route: ActivatedRouteSnapshot, state: RouterStateSnaps
return accountService.getAccountData().pipe(
filter((account) => account !== undefined),
map((account) => {
console.log(authorities, account)

if (account) {
const hasAnyAuthority = accountService.hasAnyAuthority(authorities)
if (hasAnyAuthority) {
Expand Down
1 change: 0 additions & 1 deletion ui/src/app/account/login/login.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@

ngOnDestroy(): void {
this.sub?.unsubscribe()
console.log('test')
}

ngAfterViewInit() {
Expand Down Expand Up @@ -72,8 +71,8 @@

this.loginService
.login({
username: this.loginForm.get('username')!.value!,

Check warning on line 74 in ui/src/app/account/login/login.component.ts

View workflow job for this annotation

GitHub Actions / format

Forbidden non-null assertion

Check warning on line 74 in ui/src/app/account/login/login.component.ts

View workflow job for this annotation

GitHub Actions / format

Forbidden non-null assertion
password: this.loginForm.get('password')!.value!,

Check warning on line 75 in ui/src/app/account/login/login.component.ts

View workflow job for this annotation

GitHub Actions / format

Forbidden non-null assertion

Check warning on line 75 in ui/src/app/account/login/login.component.ts

View workflow job for this annotation

GitHub Actions / format

Forbidden non-null assertion
mfaCode: this.loginForm.get('mfaCode')?.value,
})
.subscribe({
Expand All @@ -98,7 +97,7 @@
this.mfaSent = false
},
// TODO: review any type
error: (err) => {

Check warning on line 100 in ui/src/app/account/login/login.component.ts

View workflow job for this annotation

GitHub Actions / format

'err' is defined but never used
this.loginService.logout()
this.authenticationError = true
},
Expand Down
6 changes: 2 additions & 4 deletions ui/src/app/account/service/account.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,8 @@ export class AccountService {
)
}

getMfaSetup(): Observable<HttpResponse<any>> {
return this.http.get<any>('/services/userservice/api/account/mfa', { observe: 'response' })
getMfaSetup(): Observable<{ secret: string; otp: string; qrCode: any }> {
return this.http.get<any>('/services/userservice/api/account/mfa')
}

save(account: any): Observable<HttpResponse<any>> {
Expand All @@ -90,8 +90,6 @@ export class AccountService {
}

hasAnyAuthority(authorities: string[]): boolean {
console.log(authorities, this.accountData.value?.authorities)

if (!this.authenticated || !this.accountData || !this.accountData.value?.authorities) {
return false
}
Expand Down
138 changes: 138 additions & 0 deletions ui/src/app/account/settings/settings.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8">
<h1 class="mt-3" jhiTranslate="settings.personalDetails.string">Personal details</h1>
<hr />

<div class="alert alert-success" *ngIf="success" jhiTranslate="settings.messages.success.string">
<strong>Settings saved!</strong>
</div>

<form name="form" role="form" (ngSubmit)="save()" [formGroup]="settingsForm" *ngIf="settingsForm.get('email')?.value" novalidate>
<div class="form-group">
<label class="form-control-label" for="firstName" jhiTranslate="settings.form.firstname.label.string">First Name</label>
<!-- TODO: translate pipe removed -->
<input type="text" class="form-control" id="firstName" name="firstName" placeholder="{{'settings.form.firstname.placeholder.string' }}"
formControlName="firstName">
<div *ngIf="settingsForm.get('firstName')?.invalid && (settingsForm.get('firstName')?.dirty || settingsForm.get('firstName')?.touched)">
<small class="form-text text-danger"
*ngIf="settingsForm.get('firstName')?.errors!['required']" jhiTranslate="settings.messages.validate.firstname.required.string">
Your first name is required.
</small>
<small class="form-text text-danger"
*ngIf="settingsForm.get('firstName')?.errors!['minlength']" jhiTranslate="settings.messages.validate.firstname.minlength.string">
Your first name is required to be at least 1 character.
</small>
<small class="form-text text-danger"
*ngIf="settingsForm.get('firstName')?.errors!['maxlength']" jhiTranslate="settings.messages.validate.firstname.maxlength.string">
Your first name cannot be longer than 50 characters.
</small>
</div>
</div>
<div class="form-group">
<label class="form-control-label" for="lastName" jhiTranslate="settings.form.lastname.label.string">Last Name</label>
<!-- TODO: translate pipe removed -->

<input type="text" class="form-control" id="lastName" name="lastName" placeholder="{{'settings.form.lastname.placeholder.string'}}"
formControlName="lastName">
<div *ngIf="settingsForm.get('lastName')?.invalid && (settingsForm.get('lastName')?.dirty || settingsForm.get('lastName')?.touched)">
<small class="form-text text-danger"
*ngIf="settingsForm.get('lastName')?.errors!['required']" jhiTranslate="settings.messages.validate.lastname.required.string">
Your last name is required.
</small>
<small class="form-text text-danger"
*ngIf="settingsForm.get('lastName')?.errors!['minlength']" jhiTranslate="settings.messages.validate.lastname.minlength.string">
Your last name is required to be at least 1 character.
</small>
<small class="form-text text-danger"
*ngIf="settingsForm.get('lastName')?.errors!['maxlength']" jhiTranslate="settings.messages.validate.lastname.maxlength.string">
Your last name cannot be longer than 50 characters.
</small>
</div>
</div>
<div class="form-group">
<label class="form-control-label" for="email" jhiTranslate="global.form.email.label.string">Email</label>
<!-- TODO: translate pipe removed -->
<input type="email" class="form-control" id="email" name="email" placeholder="{{'global.form.email.placeholder.string'}}"
formControlName="email" readonly>

</div>
<div class="form-group" *ngIf="languages && languages.length > 0">
<label class="form-control-label" for="langKey" jhiTranslate="settings.form.language.string">Language</label>
<select class="form-control" id="langKey" name="langKey" formControlName="langKey">
<option *ngFor="let language of languages" [value]="language">{{language | findLanguageFromKey}}</option>
</select>
</div>
<button type="submit" [disabled]="settingsForm.invalid || settingsForm.pristine" class="btn btn-primary" jhiTranslate="settings.form.button.string">Save</button>
</form>
<hr />

<form name="form" role="form" (ngSubmit)="saveMfa()"
[formGroup]="mfaForm" *ngIf="settingsForm.get('email')?.value"
novalidate>
<h1 class="mt-3" jhiTranslate="settings.security.heading.string">Security</h1>
<hr />
<div class="form-group">
<p jhiTranslate="settings.security.mfaExplain.string">Add extra security to your ORCID member portal account by enabling two-factor authentication. Each time you sign in, you'll be prompted to enter a six-digit code we send to your preferred authentication application.</p>
<label class="form-control-label" for="field_mfaEnabled"
jhiTranslate="settings.security.mfa.string">Two-factor
Authentication</label>
<input type="checkbox" class="form-control"
name="mfaEnabled" id="field_mfaEnabled"
formControlName="mfaEnabled" (change)="mfaEnabledStateChange()" />
</div>
<div *ngIf="showMfaUpdated" jhiTranslate="settings.security.mfaUpdated.string">2FA settings updated</div>
<div class="row" *ngIf="showMfaSetup && !showMfaBackupCodes">
<div class="col-md-8">
<ul>
<li jhiTranslate="settings.security.mfaQrCodeSteps.one.string">Install a two-factor authentication app<br />A 2FA app is required to create the six-digit code you need to access your account each time you sign in. Most apps are for mobile devices; some are also available as desktop or web-based apps. Download and install your preferred 2FA app, such as <a href='https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2'>Google Authenticator</a>, <a href='https://freeotp.github.io/'>FreeOTP</a>, or <a href='https://authy.com/'>Authy</a>.</li>
<li jhiTranslate="settings.security.mfaQrCodeSteps.two.string">Scan this QR code with your device<br />Open your 2FA app and scan the image below.</li>
</ul>
</div>
</div>
<div class="row" *ngIf="showMfaSetup && !showMfaBackupCodes">
<div class="col-md-8">
<img [src]="safeQrCode()" alt="QR Code" />
</div>
</div>
<div class="row" *ngIf="showMfaSetup && !showMfaBackupCodes && showMfaTextCode">
<div class="col-md-8">
<p class="mfaSecret"><strong>{{ mfaSetup.secret }}</strong></p>
</div>
</div>
<div class="row" *ngIf="showMfaSetup && !showMfaBackupCodes">
<div class="col-md-8">
<ul>
<li><span jhiTranslate="settings.security.mfaCannotScan.one.string">Can't scan the QR code?</span><br /><a href="JavaScript:void(0);" (click)="toggleMfaTextCode()" jhiTranslate="settings.security.mfaCannotScan.two.string">Get a text code</a>&nbsp;<span jhiTranslate="settings.security.mfaCannotScan.three.string">and enter it into your 2FA app instead</span></li>
<li jhiTranslate="settings.security.mfaTextCodeSteps.one.string">Enter the six-digit code from the app<br />After scanning the QR code or entering in the text code, your 2FA app will display a six-digit code. Enter this code in the box below and click Save.</li>
</ul>
</div>
</div>
<div class="form-group" *ngIf="showMfaSetup && !showMfaBackupCodes">
<div class="col-md-8">
<div *ngIf="mfaSetupFailure" class="alert alert-danger" jhiTranslate="settings.security.otpError.string">
Incorrect verification code
</div>
<!-- TODO: translate pipe removed -->

<input class="indented" name="verificationCode" formControlName="verificationCode"
placeholder="{{'settings.security.verificationCode.string'}}" />
</div>
</div>
<div class="row" *ngIf="showMfaBackupCodes && showMfaSetup">
<div class="col-md-8">
<p jhiTranslate="settings.security.backupCodes.string">Make a note of the following backup codes, this is the only time they will be shown.</p>
<table>
<tr *ngFor="let backupCode of mfaBackupCodes">
<td>{{ backupCode }}</td>
</tr>
</table>
</div>
</div>
<button [disabled]="mfaForm.pristine || showMfaBackupCodes" type="submit" class="btn btn-primary" jhiTranslate="settings.form.button.string">Save</button>
</form>
<hr />
</div>
</div>

</div>
Empty file.
Loading
Loading