Skip to content

Commit

Permalink
Merge branch 'main' into userList
Browse files Browse the repository at this point in the history
  • Loading branch information
auumgn committed Jan 22, 2024
2 parents 0d5ff31 + a00d74f commit e9b4a3c
Show file tree
Hide file tree
Showing 27 changed files with 2,722 additions and 509 deletions.
5 changes: 2 additions & 3 deletions ui/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ WORKDIR /app
# Install some useful utils for debug/test
RUN \
apt-get update && \
apt -y install python3 make gcc g++ && \
apt -y install python3 make gcc g++ vim && \
rm -rf /var/lib/apt/lists/*

# Install app dependencies
Expand All @@ -19,8 +19,7 @@ COPY package*.json ./

RUN \
npm config list && \
npm config delete proxy && \
npm install --loglevel silly
npm install

# Bundle app source
COPY . .
Expand Down
25 changes: 18 additions & 7 deletions ui/container-files/etc/nginx/conf.d/default.conf
Original file line number Diff line number Diff line change
@@ -1,26 +1,37 @@
map $cookie_locale $langCode {
default en;
~*^cs cs;
~*^de de;
~*^es es;
~*^fr fr;
~*^it it;
~*^ja ja;
~*^ko ko;
~*^pt pt;
~*^ru ru;
~*^ui ui;
~*^zh-CN zh-CN;
~*^zh-TW zh-TW;
}

server {
listen 8090;
server_name localhost;

#access_log /var/log/nginx/host.access.log main;

# Fallback to default language if no preference defined by browser
if ($accept_language ~ "^$") {
set $accept_language "en";
}

location / {
root /usr/share/nginx/html;
index index.html index.htm;

location ~ ^/ui/(.*) {
# Redirect requests for `/ui/(.*)` to the Angular application in the preferred language of the browser
# For reference on multi language support see: https://angular.io/guide/i18n-common-deploy#configure-a-server
rewrite ^/ui/(.*)$ /$accept_language/$1 break;
rewrite ^/ui/(.*)$ /${langCode}/$1 break;

# Configure a fallback route in the NGinX server to serve the index.html when requests arrive for `/ui/login`
# Requires static html content to have a `base-href=./` entry
try_files $uri $uri/ /$accept_language/index.html?$args;
try_files $uri $uri/ /${langCode}/index.html?$args;

# Or use the following line instead
# auto-index on;
Expand Down
18 changes: 0 additions & 18 deletions ui/container-files/etc/nginx/nginx.conf
Original file line number Diff line number Diff line change
Expand Up @@ -25,24 +25,6 @@ http {

#gzip on;

# Browser preferred language detection (does NOT require AcceptLanguageModule)
# For reference on multi language support see: https://angular.io/guide/i18n-common-deploy#configure-a-server
map $http_accept_language $accept_language {
default en;
~*^cs cs;
~*^de de;
~*^es es;
~*^fr fr;
~*^it it;
~*^ja ja;
~*^ko ko;
~*^pt pt;
~*^ru ru;
~*^ui ui;
~*^zh-CN zh-CN;
~*^zh-TW zh-TW;
}

include /etc/nginx/conf.d/*.conf;

}
4 changes: 3 additions & 1 deletion ui/src/app/account/account.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import { PasswordResetInitComponent } from './password/password-reset-init.compo
import { SettingsComponent } from './settings/settings.component'
import { SharedModule } from '../shared/shared.module'
import { PasswordComponent } from './password/password.component'
import { PasswordStrengthComponent } from './password/password-strength.component'
import { PasswordStrengthComponent } from './password/password-strength.component';
import { PasswordResetFinishComponent } from './password/password-reset-finish.component'

@NgModule({
declarations: [
Expand All @@ -17,6 +18,7 @@ import { PasswordStrengthComponent } from './password/password-strength.componen
SettingsComponent,
PasswordComponent,
PasswordStrengthComponent,
PasswordResetFinishComponent,
],
imports: [SharedModule, CommonModule, ReactiveFormsModule, RouterModule.forChild(routes)],
})
Expand Down
9 changes: 9 additions & 0 deletions ui/src/app/account/account.route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { PasswordResetInitComponent } from './password/password-reset-init.compo
import { SettingsComponent } from './settings/settings.component'
import { AuthGuard } from './auth.guard'
import { PasswordComponent } from './password/password.component'
import { PasswordResetFinishComponent } from './password/password-reset-finish.component'

export const routes: Routes = [
{
Expand All @@ -18,6 +19,14 @@ export const routes: Routes = [
pageTitle: 'global.menu.account.password.string',
},
},
{
path: 'reset/finish',
component: PasswordResetFinishComponent,
data: {
authorities: [],
pageTitle: 'global.menu.account.password.string'
}
},
{
path: 'settings',
component: SettingsComponent,
Expand Down
14 changes: 14 additions & 0 deletions ui/src/app/account/model/key-validation-result.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
export interface IKeyValidationResult {
expiredKey: boolean
invalidKey: boolean
}

export class KeyValidationResult implements IKeyValidationResult {
expiredKey: boolean
invalidKey: boolean

constructor(expiredKey: boolean, invalidKey: boolean) {
this.expiredKey = expiredKey
this.invalidKey = invalidKey
}
}
11 changes: 11 additions & 0 deletions ui/src/app/account/model/resend-activation-email-result.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export interface IResendActivationEmailResult {
resent: boolean
}

export class ResendActivationEmailResult implements IResendActivationEmailResult {
resent: boolean

constructor(resent: boolean) {
this.resent = resent
}
}
166 changes: 166 additions & 0 deletions ui/src/app/account/password/password-reset-finish.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
<div class="container">
<div class="row">
<div class="col-md-12">
<h1 i18n="@@reset.finish.title.string">Reset password</h1>

<div class="alert alert-danger" i18n="@@reset.finish.messages.keymissing.string" *ngIf="keyMissing">
<strong>The activation key is missing.</strong>
</div>

<div class="alert alert-danger" i18n="@@reset.finish.messages.keyinvalid.string" *ngIf="invalidKey">
<strong>This activation key is invalid.</strong>
</div>

<div class="alert alert-danger" i18n="@@reset.finish.messages.keyexpired.string" *ngIf="expiredKey">
<strong>This activation has expired.</strong>
</div>
<div *ngIf="expiredKey">
<p>
<span i18n="@@reset.finish.messages.keyexpired.paragraph1.string"
>ORCID Member Portal activation links are only valid for 24 hours. It looks like this link has
expired.</span
>
</p>
<p>
<span *ngIf="activationEmailResent" i18n="@@reset.finish.messages.keyexpired.paragraph2.string"
>To make sure you can activate your Member Portal account we have sent a new activation link to your
registered email address.</span
>
</p>
<p>
<span *ngIf="activationEmailResent" i18n="@@reset.finish.messages.keyexpired.paragraph3.string"
>If you are still having problems activating your account or have not received your new activation link
please contact our support team please contact us at membership&#64;orcid.org.</span
>
</p>
</div>

<div class="alert alert-warning" *ngIf="!success && !keyMissing && !expiredKey && !invalidKey">
<p i18n="@@reset.finish.messages.info.string">Choose a new password</p>
</div>

<div class="alert alert-danger" *ngIf="error">
<p i18n="@@reset.finish.messages.error.string">
Your password couldn't be reset. Remember a password request is only valid for 24 hours.
</p>
</div>

<p class="alert alert-success" *ngIf="success">
<span i18n="@@reset.finish.messages.success.string"
><strong>Your password has been reset.</strong> Please
</span>
<a
class="alert-link"
tabindex="0"
(click)="navigateToLoginPage()"
(keydown.enter)="navigateToLoginPage()"
i18n="@@global.messages.info.authenticated.link.string"
>sign in</a
>.
</p>

<div class="alert alert-danger" *ngIf="doNotMatch" i18n="@@global.messages.error.dontmatch.string">
The password and its confirmation do not match!
</div>

<div *ngIf="!keyMissing && showPasswordForm">
<form *ngIf="!success" name="form" role="form" (ngSubmit)="finishReset()" [formGroup]="passwordForm">
<div class="form-group">
<label class="form-control-label" for="password" i18n="@@global.form.newpassword.label.string"
>New password</label
>
<input
type="password"
class="form-control"
id="password"
name="password"
placeholder="New password"
i18n-placeholder="@@global.form.newpassword.placeholder.string"
formControlName="newPassword"
/>
<div
*ngIf="
passwordForm.get('newPassword')?.['invalid'] &&
(passwordForm.get('newPassword')?.['dirty'] || passwordForm.get('newPassword')?.['touched'])
"
>
<small
class="form-text text-danger"
*ngIf="(passwordForm.get('newPassword')?.errors)!['required']"
i18n="@@global.messages.validate.newpassword.required.string"
>
Your password is required.
</small>
<small
class="form-text text-danger"
*ngIf="(passwordForm.get('newPassword')?.errors)!['minlength']"
i18n="@@global.messages.validate.newpassword.minlength.string"
>
Your password is required to be at least 4 characters.
</small>
<small
class="form-text text-danger"
*ngIf="(passwordForm.get('newPassword')?.errors)!['maxlength']"
i18n="@@global.messages.validate.newpassword.maxlength.string"
>
Your password cannot be longer than 50 characters.
</small>
</div>
<app-password-strength [passwordToCheck]="passwordForm.get('newPassword')?.value"></app-password-strength>
</div>

<div class="form-group">
<label class="form-control-label" for="confirmPassword" i18n="@@global.form.confirmpassword.label.string"
>New password confirmation</label
>
<input
type="password"
class="form-control"
id="confirmPassword"
name="confirmPassword"
placeholder="Confirm the new password"
i18n-placeholder="@@global.form.confirmpassword.placeholder.string"
formControlName="confirmPassword"
/>
<div
*ngIf="
passwordForm.get('confirmPassword')?.['invalid'] &&
(passwordForm.get('confirmPassword')?.['dirty'] || passwordForm.get('confirmPassword')?.['touched'])
"
>
<small
class="form-text text-danger"
*ngIf="(passwordForm.get('confirmPassword')?.errors)!['required']"
i18n="@@global.messages.validate.confirmpassword.required.string"
>
Your password confirmation is required.
</small>
<small
class="form-text text-danger"
*ngIf="(passwordForm.get('confirmPassword')?.errors)!['minlength']"
i18n="@@global.messages.validate.confirmpassword.minlength.string"
>
Your password confirmation is required to be at least 4 characters.
</small>
<small
class="form-text text-danger"
*ngIf="(passwordForm.get('confirmPassword')?.errors)!['maxlength']"
i18n="@@global.messages.validate.confirmpassword.maxlength.string"
>
Your password confirmation cannot be longer than 50 characters.
</small>
</div>
</div>
<button
type="submit"
[disabled]="passwordForm.invalid"
class="btn btn-primary"
i18n="@@reset.finish.form.button.string"
>
Reset Password
</button>
</form>
</div>
</div>
</div>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { PasswordResetFinishComponent } from './password-reset-finish.component';
import { AppModule } from 'src/app/app.module';
import { PasswordService } from '../service/password.service';
import { of, throwError } from 'rxjs';

describe('PasswordResetFinishComponent', () => {
let component: PasswordResetFinishComponent;
let fixture: ComponentFixture<PasswordResetFinishComponent>;
let service: PasswordService;

beforeEach(() => {
TestBed.configureTestingModule({
imports: [AppModule],
declarations: [PasswordResetFinishComponent]
});
fixture = TestBed.createComponent(PasswordResetFinishComponent);
service = fixture.debugElement.injector.get(PasswordService)
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});

it('password should save successfully', () => {
spyOn(service, 'savePassword').and.returnValue(of(true))
component.finishReset();
expect(component.success).toEqual('OK')
});

it('password save should fail', () => {
spyOn(service, 'savePassword').and.returnValue(throwError(() => new Error('error')))
component.finishReset();
expect(component.error).toEqual('ERROR')
expect(component.success).toBeFalsy();
});
});
Loading

0 comments on commit e9b4a3c

Please sign in to comment.