fix(console): initialize org owner with or without password (#471)

* set password validators only if needed

* create org initialize without pwd

* no caps

* self xss message
This commit is contained in:
Max Peintner 2020-07-15 09:04:45 +02:00 committed by GitHub
parent c051fa8ae1
commit 30282acb42
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 148 additions and 113 deletions

View File

@ -155,7 +155,7 @@ export class AppComponent implements OnDestroy {
update: UpdateService,
) {
console.log('%cWait!', 'text-shadow: -1px 0 black, 0 1px black, 1px 0 black, 0 -1px black; color: #5282c1; font-size: 50px');
console.log('%cInserting something here could give attackers access to your caos account.', 'color: red; font-size: 18px');
console.log('%cInserting something here could give attackers access to your zitadel account.', 'color: red; font-size: 18px');
console.log('%cIf you don\'t know exactly what you\'re doing, close the window and stay on the safe side', 'font-size: 16px');
console.log('%cIf you know exactly what you are doing, you should work for us', 'font-size: 16px');
this.setLanguage();

View File

@ -10,7 +10,7 @@
<ng-container *ngIf="currentCreateStep == 1">
<h1>{{'ORG.PAGES.ORGDETAIL_TITLE' | translate}}</h1>
<form [formGroup]="orgForm">
<form [formGroup]="orgForm" (ngSubmit)="next()">
<div class="content">
<mat-form-field class="formfield">
<mat-label>{{ 'ORG_DETAIL.DETAIL.NAME' | translate }}</mat-label>
@ -21,6 +21,11 @@
<input matInput formControlName="domain" />
</mat-form-field>
</div>
<button [disabled]="orgForm.invalid" color="primary" mat-raised-button class="continue-button"
cdkFocusInitial type="submit">
{{'CONTINUE' | translate}}
</button>
</form>
<!-- <div *ngIf="name?.touched" @openClose>
@ -107,61 +112,66 @@
</mat-select>
</mat-form-field>
<p class="section">{{ 'USER.CREATE.PASSWORDSECTION' | translate }}</p>
<mat-checkbox [(ngModel)]="usePassword" [ngModelOptions]="{standalone: true}"
(change)="initPwdValidators()">
{{'ORG.PAGES.USEPASSWORD' | translate}}</mat-checkbox>
<mat-form-field class="formfield">
<mat-label>{{ 'USER.PASSWORD.NEW' | translate }}</mat-label>
<input autocomplete="off" name="firstpassword" matInput formControlName="password"
type="password" />
<ng-container *ngIf="usePassword">
<p class="section">{{ 'USER.CREATE.PASSWORDSECTION' | translate }}</p>
<mat-error *ngIf="password?.errors?.required">
{{ 'USER.VALIDATION.REQUIRED' | translate }}
</mat-error>
<mat-error *ngIf="password?.errors?.symbolValidator">
{{ 'USER.VALIDATION.SYMBOLERROR' | translate }}
</mat-error>
<mat-error *ngIf="password?.errors?.numberValidator">
{{ 'USER.VALIDATION.NUMBERERROR' | translate }}
</mat-error>
<mat-error *ngIf="password?.errors?.upperCaseValidator">
{{ 'USER.VALIDATION.UPPERCASEMISSING' | translate }}
</mat-error>
<mat-error *ngIf="password?.errors?.lowerCaseValidator">
{{ 'USER.VALIDATION.LOWERCASEMISSING' | translate }}
</mat-error>
<mat-error *ngIf="password?.errors?.minlength">
{{ 'USER.VALIDATION.MINLENGTH' | translate:password?.errors?.minlength }}
</mat-error>
</mat-form-field>
<mat-form-field class="formfield">
<mat-label>{{ 'USER.PASSWORD.CONFIRM' | translate }}</mat-label>
<input autocomplete="off" name="confirmPassword" matInput formControlName="confirmPassword"
type="password" />
<mat-form-field class="formfield" *ngIf="password">
<mat-label>{{ 'USER.PASSWORD.NEW' | translate }}</mat-label>
<input autocomplete="off" name="firstpassword" matInput formControlName="password"
type="password" />
<mat-error *ngIf="password?.errors?.required">
{{ 'USER.VALIDATION.REQUIRED' | translate }}
</mat-error>
<mat-error *ngIf="password?.errors?.symbolValidator">
{{ 'USER.VALIDATION.SYMBOLERROR' | translate }}
</mat-error>
<mat-error *ngIf="password?.errors?.numberValidator">
{{ 'USER.VALIDATION.NUMBERERROR' | translate }}
</mat-error>
<mat-error *ngIf="password?.errors?.upperCaseValidator">
{{ 'USER.VALIDATION.UPPERCASEMISSING' | translate }}
</mat-error>
<mat-error *ngIf="password?.errors?.lowerCaseValidator">
{{ 'USER.VALIDATION.LOWERCASEMISSING' | translate }}
</mat-error>
<mat-error *ngIf="password?.errors?.minlength">
{{ 'USER.VALIDATION.MINLENGTH' | translate:password?.errors?.minlength }}
</mat-error>
</mat-form-field>
<mat-form-field class="formfield" *ngIf="confirmPassword">
<mat-label>{{ 'USER.PASSWORD.CONFIRM' | translate }}</mat-label>
<input autocomplete="off" name="confirmPassword" matInput formControlName="confirmPassword"
type="password" />
<mat-error *ngIf="confirmPassword?.errors?.required">
{{ 'USER.VALIDATION.REQUIRED' | translate }}
</mat-error>
<mat-error *ngIf="confirmPassword?.errors?.symbolValidator">
{{ 'USER.VALIDATION.SYMBOLERROR' | translate }}
</mat-error>
<mat-error *ngIf="confirmPassword?.errors?.numberValidator">
{{ 'USER.VALIDATION.NUMBERERROR' | translate }}
</mat-error>
<mat-error *ngIf="confirmPassword?.errors?.notequal">
{{ 'USER.PASSWORD.NOTEQUAL' | translate }}
</mat-error>
<mat-error *ngIf="confirmPassword?.errors?.upperCaseValidator">
{{ 'USER.VALIDATION.UPPERCASEMISSING' | translate }}
</mat-error>
<mat-error *ngIf="confirmPassword?.errors?.lowerCaseValidator">
{{ 'USER.VALIDATION.LOWERCASEMISSING' | translate }}
</mat-error>
<mat-error *ngIf="confirmPassword?.errors?.minlength">
{{ 'USER.VALIDATION.MINLENGTH' | translate:confirmPassword?.errors?.minlength }}
</mat-error>
</mat-form-field>
<mat-error *ngIf="confirmPassword?.errors?.required">
{{ 'USER.VALIDATION.REQUIRED' | translate }}
</mat-error>
<mat-error *ngIf="confirmPassword?.errors?.symbolValidator">
{{ 'USER.VALIDATION.SYMBOLERROR' | translate }}
</mat-error>
<mat-error *ngIf="confirmPassword?.errors?.numberValidator">
{{ 'USER.VALIDATION.NUMBERERROR' | translate }}
</mat-error>
<mat-error *ngIf="confirmPassword?.errors?.notequal">
{{ 'USER.PASSWORD.NOTEQUAL' | translate }}
</mat-error>
<mat-error *ngIf="confirmPassword?.errors?.upperCaseValidator">
{{ 'USER.VALIDATION.UPPERCASEMISSING' | translate }}
</mat-error>
<mat-error *ngIf="confirmPassword?.errors?.lowerCaseValidator">
{{ 'USER.VALIDATION.LOWERCASEMISSING' | translate }}
</mat-error>
<mat-error *ngIf="confirmPassword?.errors?.minlength">
{{ 'USER.VALIDATION.MINLENGTH' | translate:confirmPassword?.errors?.minlength }}
</mat-error>
</mat-form-field>
</ng-container>
</div>
<div class="btn-container">
<button color="primary" class="continue-button" [disabled]="orgForm.invalid || userForm.invalid"
@ -170,11 +180,4 @@
</form>
</div>
</ng-container>
<ng-container *ngIf="currentCreateStep == 1">
<button (click)="next()" color="primary" mat-raised-button class="continue-button" cdkFocusInitial
type="submit">
{{'CONTINUE' | translate}}
</button>
</ng-container>
</div>

View File

@ -140,3 +140,7 @@ h1 {
border-radius: 0.5rem;
}
mat-checkbox {
flex-basis: 100%;
margin: .5rem;
}

View File

@ -7,7 +7,7 @@ import { lowerCaseValidator, numberValidator, symbolValidator, upperCaseValidato
import { CreateOrgRequest, CreateUserRequest, Gender, OrgSetUpResponse } from 'src/app/proto/generated/admin_pb';
import { PasswordComplexityPolicy } from 'src/app/proto/generated/auth_pb';
import { AdminService } from 'src/app/services/admin.service';
import { AuthUserService } from 'src/app/services/auth-user.service';
import { OrgService } from 'src/app/services/org.service';
import { ToastService } from 'src/app/services/toast.service';
function passwordConfirmValidator(c: AbstractControl): any {
@ -54,14 +54,14 @@ export class OrgCreateComponent {
public languages: string[] = ['de', 'en'];
public policy!: PasswordComplexityPolicy.AsObject;
public usePassword: boolean = false;
constructor(
private router: Router,
private toast: ToastService,
private adminService: AdminService,
private _location: Location,
private fb: FormBuilder,
private authUserService: AuthUserService,
private orgService: OrgService,
) {
const validators: Validators[] = [];
@ -69,49 +69,8 @@ export class OrgCreateComponent {
name: ['', [Validators.required]],
domain: [''],
});
this.authUserService.GetMyPasswordComplexityPolicy().then(data => {
this.policy = data.toObject();
if (this.policy.minLength) {
validators.push(Validators.minLength(this.policy.minLength));
}
if (this.policy.hasLowercase) {
validators.push(lowerCaseValidator);
}
if (this.policy.hasUppercase) {
validators.push(upperCaseValidator);
}
if (this.policy.hasNumber) {
validators.push(numberValidator);
}
if (this.policy.hasSymbol) {
validators.push(symbolValidator);
}
this.userForm = this.fb.group({
userName: ['', [Validators.required]],
firstName: ['', [Validators.required]],
lastName: ['', [Validators.required]],
email: ['', [Validators.required]],
gender: [''],
nickName: [''],
preferredLanguage: [''],
password: ['', validators],
confirmPassword: ['', [...validators, passwordConfirmValidator]],
});
}).catch(error => {
console.error(error);
this.userForm = this.fb.group({
userName: ['', [Validators.required]],
firstName: ['', [Validators.required]],
lastName: ['', [Validators.required]],
email: ['', [Validators.required]],
gender: [''],
nickName: [''],
preferredLanguage: [''],
password: ['', validators],
confirmPassword: ['', [...validators, passwordConfirmValidator]],
});
});
this.initForm();
}
public createSteps: number = 2;
@ -150,6 +109,66 @@ export class OrgCreateComponent {
this.currentCreateStep--;
}
private initForm(pwdValidators?: Validators[]): void {
if (pwdValidators) {
console.log('init with pwd');
this.userForm = this.fb.group({
userName: ['', [Validators.required]],
firstName: ['', [Validators.required]],
lastName: ['', [Validators.required]],
email: ['', [Validators.required]],
gender: [''],
nickName: [''],
preferredLanguage: [''],
password: ['', [...pwdValidators]],
confirmPassword: ['', [...pwdValidators, passwordConfirmValidator]],
});
} else {
console.log('init without pwd');
this.userForm = this.fb.group({
userName: ['', [Validators.required]],
firstName: ['', [Validators.required]],
lastName: ['', [Validators.required]],
email: ['', [Validators.required]],
gender: [''],
nickName: [''],
preferredLanguage: [''],
});
}
}
public initPwdValidators(): void {
const validators: Validators[] = [Validators.required];
console.log(this.usePassword);
if (this.usePassword) {
this.orgService.GetDefaultPasswordComplexityPolicy().then(data => {
this.policy = data.toObject();
console.log(this.policy);
if (this.policy.minLength) {
validators.push(Validators.minLength(this.policy.minLength));
}
if (this.policy.hasLowercase) {
validators.push(lowerCaseValidator);
}
if (this.policy.hasUppercase) {
validators.push(upperCaseValidator);
}
if (this.policy.hasNumber) {
validators.push(numberValidator);
}
if (this.policy.hasSymbol) {
validators.push(symbolValidator);
}
this.initForm(validators);
});
} else {
this.initForm();
}
}
public get name(): AbstractControl | null {
return this.orgForm.get('name');
}

View File

@ -2,6 +2,7 @@ import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import { MatCheckboxModule } from '@angular/material/checkbox';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatIconModule } from '@angular/material/icon';
import { MatInputModule } from '@angular/material/input';
@ -26,6 +27,7 @@ import { OrgCreateComponent } from './org-create.component';
MatSelectModule,
PipesModule,
TranslateModule,
MatCheckboxModule,
],
})
export class OrgCreateModule { }

View File

@ -58,7 +58,6 @@
padding: .5rem 0;
.left-desc {
text-transform: uppercase;
color: #8795a1;
font-size: .9rem;
}

View File

@ -36,8 +36,7 @@
</app-card>
<ng-template appHasRole [appHasRole]="['user.read', 'user.read:'+user?.id]">
<app-card title="{{ 'USER.PROFILE.TITLE' | translate }}"
description="{{'USER.PROFILE.DESCRIPTION' | translate}}">
<app-card title="{{ 'USER.PROFILE.TITLE' | translate }}">
<app-detail-form
*ngIf="((authUserService.isAllowed(['user.write:' + user?.id, 'user.write']) | async) || false) as canwrite"
[disabled]="canwrite" [genders]="genders" [languages]="languages" [profile]="user"

View File

@ -43,9 +43,7 @@
<td mat-cell *matCellDef="let user">
<mat-checkbox color="primary" (click)="$event.stopPropagation()"
(change)="$event ? selection.toggle(user) : null" [checked]="selection.isSelected(user)">
<app-avatar *ngIf="user && (user.displayName || (user.firstName && user.lastName))"
class="avatar"
[name]="user.displayName ? user.displayName : (user.firstName + ' '+ user.lastName)"
<app-avatar *ngIf="user && user.displayName" class="avatar" [name]="user.displayName"
[size]="32">
</app-avatar>
</mat-checkbox>

View File

@ -68,6 +68,15 @@ export class OrgService {
);
}
public async GetDefaultPasswordComplexityPolicy(): Promise<PasswordComplexityPolicy> {
const req: Empty = new Empty();
return await this.request(
c => c.getDefaultPasswordComplexityPolicy,
req,
f => f,
);
}
public async GetMyOrg(): Promise<Org> {
return await this.request(
c => c.getMyOrg,

View File

@ -245,7 +245,8 @@
"DOWNLOAD_FILE":"Datei download",
"SELECTORGTOOLTIP":"Wähle diese Organisation",
"PRIMARYDOMAIN":"Primäre Domain",
"STATE":"Status"
"STATE":"Status",
"USEPASSWORD":"Initiales Password setzen"
},
"DOMAINS": {
"NEW":"Domain hinzufügen",

View File

@ -245,7 +245,8 @@
"DOWNLOAD_FILE":"Download file",
"SELECTORGTOOLTIP":"Select this organisation",
"PRIMARYDOMAIN":"Primary Domain",
"STATE":"State"
"STATE":"State",
"USEPASSWORD":"Set initial password"
},
"DOMAINS": {
"NEW":"Add Domain",