2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing,
12 * software distributed under the License is distributed on an
13 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 * KIND, either express or implied. See the License for the
15 * specific language governing permissions and limitations
19 import {environment} from "../../../../environments/environment";
20 import {ErrorResult} from "../../../model/error-result";
21 import {UserInfo} from "../../../model/user-info";
30 } from "@angular/forms";
31 import {User} from "../../../model/user";
32 import {of, timer} from "rxjs";
33 import {catchError, map, switchMap} from "rxjs/operators";
34 import { UserService } from 'src/app/services/user.service';
36 export class ManageUsersBaseComponent {
38 editProperties = ['user_id', 'full_name', 'email', 'locked', 'password_change_required',
39 'password', 'confirm_password', 'validated'];
40 minUserIdSize = environment.application.minUserIdLength;
41 success: boolean = false;
42 error: boolean = false;
43 errorResult: ErrorResult;
47 userForm = this.fb.group({
48 user_id: ['', [Validators.required, Validators.minLength(this.minUserIdSize), whitespaceValidator()], this.userUidExistsValidator()],
49 full_name: ['', Validators.required],
50 email: ['', [Validators.required, Validators.email]],
52 password_change_required: [true],
54 confirm_password: [''],
57 validator: MustMatch('password', 'confirm_password')
60 constructor(public userService: UserService, public fb: FormBuilder) {
64 public copyFromForm(properties: string[]): User {
65 let user: any = new User();
66 for (let prop of properties) {
67 user[prop] = this.userForm.get(prop).value;
69 console.log("User " + user);
73 public copyToForm(properties: string[], user: User): void {
75 for (let prop of properties) {
76 let propValue = user[prop] == null ? '' : user[prop];
77 propMap[prop] = propValue;
79 this.userForm.patchValue(propMap);
80 console.log("User " + user);
84 valid(field: string): string[] {
85 let formField = this.userForm.get(field);
86 if (formField.dirty || formField.touched) {
87 if (formField.valid) {
98 * Async validator with debounce time
101 userUidExistsValidator() {
103 return (ctrl: FormControl) => {
104 // debounceTimer() does not work here, as the observable is created with each keystroke
105 // but angular does unsubscribe on previous started async observables.
106 return timer(500).pipe(
107 switchMap((userid) => this.userService.userExists(ctrl.value)),
108 catchError(() => of(null)),
109 map(exists => (exists ? {userexists: true} : null))
114 forbiddenNameValidator(nameRe: RegExp): ValidatorFn {
115 return (control: AbstractControl): { [key: string]: any } | null => {
116 const forbidden = nameRe.test(control.value);
117 return forbidden ? {forbiddenName: {value: control.value}} : null;
122 export function whitespaceValidator(): ValidatorFn {
123 return (control: AbstractControl): ValidationErrors | null => {
124 const hasWhitespace = /\s/g.test(control.value);
125 return hasWhitespace ? {containsWhitespace: {value: control.value}} : null;
128 export function MustMatch(controlName: string, matchingControlName: string) : ValidatorFn {
129 return (formGroup: FormGroup): ValidationErrors | null => {
130 const control = formGroup.controls[controlName];
131 const matchingControl = formGroup.controls[matchingControlName];
133 if (matchingControl.errors && !matchingControl.errors.mustMatch) {
134 // return if another validator has already found an error on the matchingControl
138 // set error on matchingControl if validation fails
139 if (control.value !== matchingControl.value) {
140 matchingControl.setErrors({mustMatch: true});
142 matchingControl.setErrors(null);