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

Add support for setup UI for local admin account #4031

Merged
merged 12 commits into from
Jan 7, 2020
Next Next commit
Add support for setup UI for local admin account
  • Loading branch information
nwmac committed Nov 29, 2019
commit 7b2034282d9ec9d1679e06f7a4dc1cb47f635848
2 changes: 1 addition & 1 deletion src/frontend/packages/core/sass/_all-theme.scss
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
@import '../src/shared/components/start-end-date/start-end-date.component.theme';
@import '../src/shared/components/metrics-chart/metrics-chart.component.theme';
@import '../src/shared/components/metrics-range-selector/metrics-range-selector.component.theme';
@import '../src/shared/components/tile-selector/tile-selector.component.theme';
@import '../src/shared/components/tile-selector-tile/tile-selector-tile.component.theme';
@import '../src/shared/components/entity-summary-title/entity-summary-title.component.theme';
@import '../src/shared/components/multiline-title/multiline-title.component.theme';
@import '../src/features/user-profile/profile-info/profile-info.component.theme';
Expand Down
21 changes: 18 additions & 3 deletions src/frontend/packages/core/src/app.routing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,28 @@ import { ConsoleUaaWizardComponent } from './features/setup/uaa-wizard/console-u
import { UpgradePageComponent } from './features/setup/upgrade-page/upgrade-page.component';
import { SharedModule } from './shared/shared.module';
import { NotSetupGuardService } from './core/not-setup-guard.service';
import { SetupWelcomeComponent } from './features/setup/setup-welcome/setup-welcome.component';
import { LocalAccountWizardComponent } from './features/setup/local-account-wizard/local-account-wizard.component';

const appRoutes: Routes = [
{ path: '', redirectTo: 'home', pathMatch: 'full' },
{
path: 'uaa',
component: ConsoleUaaWizardComponent,
canActivate: [NotSetupGuardService]
path: 'setup',
canActivate: [NotSetupGuardService],
children: [
{
path: '',
component: SetupWelcomeComponent
},
{
path: 'uaa',
component: ConsoleUaaWizardComponent
},
{
path: 'local',
component: LocalAccountWizardComponent
},
]
},
{ path: 'upgrade', component: UpgradePageComponent },
{ path: 'domainMismatch', component: DomainMismatchComponent },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ export class LoginPageComponent implements OnInit, OnDestroy {
// Setup mode
if (auth.sessionData && auth.sessionData.uaaError) {
this.subscription.unsubscribe(); // Ensure to unsub otherwise GoToState gets caught in loop
this.store.dispatch(new RouterNav({ path: ['/uaa'] }));
this.store.dispatch(new RouterNav({ path: ['/setup'] }));
return false;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<div class="page-container">
<app-page-header hideMenu="true" [showHistory]="false">
<h1>Stratos Setup with Local Admin Account</h1>
</app-page-header>
<app-show-page-header></app-show-page-header>
<div class="uaa-wizard">
<app-steppers>
<app-step title="Local Account Informatiomn" [valid]="validateUAAForm | async" [onNext]="next">
<app-loading-page [isLoading]="applyingSetup$" alert="Saving configuration"
text="Please wait - this will take a few moments">
<div class="uaa-wizard__form">
<p class="uaa-wizard__form-section">
Please choose a password to use for the local Administrator account.</p>
<p>This will configure Stratos with a single, built-in account with the username <span class="uaa-wizard__form-username">admin</span>
and the password that you choose below.</p>
<form class="uaa-wizard__form" [formGroup]="passwordForm" class="stepper-form">
<div class="uaa-wizard__form-block">
<mat-form-field>
<input matInput formControlName="adminPassword" placeholder="Password">
</mat-form-field>
<mat-form-field>
<input matInput formControlName="adminPasswordConfirm" placeholder="Confirm Password">
</mat-form-field>
</div>
</form>
</div>
</app-loading-page>
</app-step>
</app-steppers>
</div>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
.page-container {
display: flex;
flex-direction: column;
height: 100%;
}

.uaa-wizard {
display: flex;
flex: 1;
margin: 0 100px;
&__form {
display: block;
flex-direction: column;
width: 100%;
}
&__form-block {
display: flex;
flex-direction: column;
margin-left: 36px;
}
&__form-section {
margin: 12px 0 6px;
}
&__intro {
font-size: 18px;
font-weight: 600;
padding-top: 36px;
}
&__form-username {
font-family: Source Code Pro;
font-weight: bold;
}
&__sso-block {
margin-left: 28px;
margin-top: 6px;
code {
font-size: 14px;
padding-left: 6px;
}
}
form {
min-width: 400px;
width: 100%;

mat-checkbox {
padding: 6px 0;
}
}
app-steppers {
display: flex;
flex: 1;
margin: 24px 0;
> .steppers__wrapper {
flex: 1;
}
.stepper-form {
margin-top: 0;
max-width: none;
}
.mat-form-field {
max-width: 450px;
}
.steppers__contents {
margin: 0 48px;
overflow-y: auto;
}
.steppers__navigation {
margin-top: 36px;
}
}
app-stratos-title {
text-align: center;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';

import { LocalAccountWizardComponent } from './local-account-wizard.component';

describe('LocalAccountWizardComponent', () => {
let component: LocalAccountWizardComponent;
let fixture: ComponentFixture<LocalAccountWizardComponent>;

beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ LocalAccountWizardComponent ]
})
.compileComponents();
}));

beforeEach(() => {
fixture = TestBed.createComponent(LocalAccountWizardComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { Component, OnInit } from '@angular/core';
import { FormGroup, FormControl, Validators, ValidatorFn, AbstractControl } from '@angular/forms';
import { Observable, BehaviorSubject, of as obsof } from 'rxjs';
import { StepOnNextFunction } from '../../../shared/components/stepper/step/step.component';
import { Store } from '@ngrx/store';
import { InternalAppState } from '../../../../../store/src/app-state';
import { SetupUAASave } from '../../../../../store/src/actions/setup.actions';
import { filter, delay, take, map } from 'rxjs/operators';
import { UAASetupState, LocalAdminSetupData } from '../../../../../store/src/types/uaa-setup.types';
import { AuthState } from '../../../../../store/src/reducers/auth.reducer';
import { VerifySession } from '../../../../../store/src/actions/auth.actions';

@Component({
selector: 'app-local-account-wizard',
templateUrl: './local-account-wizard.component.html',
styleUrls: ['./local-account-wizard.component.scss']
})
export class LocalAccountWizardComponent implements OnInit {

passwordForm: FormGroup;
validateUAAForm: Observable<boolean>;
richard-cox marked this conversation as resolved.
Show resolved Hide resolved
applyingSetup$ = new BehaviorSubject<boolean>(false);

constructor(private store: Store<Pick<InternalAppState, 'uaaSetup' | 'auth'>>) { }

ngOnInit() {
this.passwordForm = new FormGroup({
adminPassword: new FormControl('', [Validators.required as any]),
adminPasswordConfirm: new FormControl('', [Validators.required as any])
});

let observer;
richard-cox marked this conversation as resolved.
Show resolved Hide resolved
this.validateUAAForm = new Observable(o => {
observer = o;
observer.next(false);
});

this.passwordForm.valueChanges.subscribe(() => {
richard-cox marked this conversation as resolved.
Show resolved Hide resolved
observer.next(this.passwordForm.valid);
this.passwordForm.controls.adminPasswordConfirm.setValidators([Validators.required, this.confirmPasswordValidator()]);
});
}

next: StepOnNextFunction = () => {

const data: LocalAdminSetupData = {
local_admin_password: this.passwordForm.get('adminPassword').value,
};

this.applyingSetup$.next(true);
this.store.dispatch(new SetupUAASave(data));
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull out common code

return this.store.select(s => [s.uaaSetup, s.auth]).pipe(
filter(([uaa, auth]: [UAASetupState, AuthState]) => {
return !(uaa.settingUp || auth.verifying);
}),
delay(3000),
take(10),
filter(([uaa, auth]: [UAASetupState, AuthState]) => {
const validUAASessionData = auth.sessionData && !auth.sessionData.uaaError;
if (!validUAASessionData) {
this.store.dispatch(new VerifySession());
}
return validUAASessionData;
}),
map((state: [UAASetupState, AuthState]) => {
if (!state[0].error) {
// Do a hard reload of the app
const loc = window.location;
const reload = loc.protocol + '//' + loc.host;
window.location.assign(reload);
} else {
this.applyingSetup$.next(false);
}
return {
success: !state[0].error,
message: state[0].message
};
}));
}

confirmPasswordValidator(): ValidatorFn {
return (control: AbstractControl): { [key: string]: any } => {
const same = control.value === this.passwordForm.value.adminPassword;
return same ? null : { passwordMatch: { value: control.value } };
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<div class="page-container">
<app-page-header hideMenu="true" [showHistory]="false">
<h1>Stratos Setup</h1>
</app-page-header>
<app-show-page-header></app-show-page-header>
<div class="setup">
<app-steppers>
<app-step [hideNextButton]="true">
<div class="select-step">
<app-stratos-title></app-stratos-title>
<div class="setup__config">
<p class="setup__intro">Welcome to Stratos</p>
<p>Before you can login, you need to choose how users will login to Stratos and complete the required configuration for the chosen method of authenticaion:</p>
richard-cox marked this conversation as resolved.
Show resolved Hide resolved
</div>
<div class="setup-tiles">
<app-tile-selector-tile *ngFor="let tile of tileSelectorConfig" (tileSelect)="selectionChange(tile)" [tile]="tile" [active]="true">
</app-tile-selector-tile>
</div>
</div>
</app-step>
</app-steppers>
</div>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
@import '../../../../sass/mixins';

.page-container {
display: flex;
flex-direction: column;
height: 100%;
}

.select-step {
width: calc(100vw - 320px);
}

.setup-tiles {

display: grid;
grid-column-gap: 10px;
grid-row-gap: 10px;
grid-template-columns: 100%;
margin: 0 10px;

@include breakpoint(tablet) {
grid-column-gap: 10%;
grid-template-columns: repeat(2, 1fr);
margin: 0 5%;
}

}

.setup {
display: flex;
flex: 1;
margin: 0 100px;

&__intro {
font-size: 28px;
font-weight: 600;
padding-bottom: 26px;
text-align: center;
}

&__config {
margin-bottom: 40px;
padding: 10px;
}

app-steppers {
display: flex;
flex: 1;
margin: 24px 0;
> .steppers__wrapper {
flex: 1;
width: 100%;
}
.stepper-form {
margin-top: 0;
max-width: none;
}
.mat-form-field {
max-width: 450px;
}
.steppers__contents {
margin: 0 48px;
overflow-y: auto;
}
.steppers__navigation {
margin-top: 36px;
}
}

app-stratos-title {
text-align: center;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';

import { SetupWelcomeComponent } from './setup-welcome.component';

describe('SetupWelcomeComponent', () => {
let component: SetupWelcomeComponent;
let fixture: ComponentFixture<SetupWelcomeComponent>;

beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ SetupWelcomeComponent ]
})
.compileComponents();
}));

beforeEach(() => {
fixture = TestBed.createComponent(SetupWelcomeComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

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