File

src/app/core/auth/user-form/user-form.component.ts

Implements

OnInit

Metadata

selector cd-user-form
styleUrls ./user-form.component.scss
templateUrl ./user-form.component.html

Index

Properties
Methods

Constructor

constructor(authService: AuthService, authStorageService: AuthStorageService, route: ActivatedRoute, router: Router, modalService: BsModalService, roleService: RoleService, userService: UserService, notificationService: NotificationService, i18n: I18n, actionLabels: ActionLabelsI18n)
Parameters :
Name Type Optional
authService AuthService No
authStorageService AuthStorageService No
route ActivatedRoute No
router Router No
modalService BsModalService No
roleService RoleService No
userService UserService No
notificationService NotificationService No
i18n I18n No
actionLabels ActionLabelsI18n No

Methods

createAction
createAction()
Returns : void
createForm
createForm()
Returns : void
disableForEdit
disableForEdit()
Returns : void
Private doEditAction
doEditAction()
Returns : void
editAction
editAction()
Returns : void
getRequest
getRequest()
Returns : UserFormModel
Private hasUserReadUpdatePermissions
hasUserReadUpdatePermissions(roles: Array)
Parameters :
Name Type Optional Default value
roles Array<string> No []
Returns : any
initEdit
initEdit()
Returns : void
Private isCurrentUser
isCurrentUser()
Returns : boolean
Private isUserChangingRoles
isUserChangingRoles()
Returns : boolean
Private isUserRemovingNeededRolePermissions
isUserRemovingNeededRolePermissions()
Returns : boolean
ngOnInit
ngOnInit()
Returns : void
setResponse
setResponse(response: UserFormModel)
Parameters :
Name Type Optional
response UserFormModel No
Returns : void
submit
submit()
Returns : void

Properties

action
Type : string
Public actionLabels
Type : ActionLabelsI18n
allRoles
Type : Array<UserFormRoleModel>
messages
Default value : new SelectMessages({ empty: 'There are no roles.' }, this.i18n)
modalRef
Type : BsModalRef
mode
Type : UserFormMode
removeSelfUserReadUpdatePermissionTpl
Type : TemplateRef<any>
Decorators :
@ViewChild('removeSelfUserReadUpdatePermissionTpl')
resource
Type : string
response
Type : UserFormModel
userForm
Type : CdFormGroup
userFormMode
Default value : UserFormMode
import { Component, OnInit, TemplateRef, ViewChild } from '@angular/core';
import { FormControl, Validators } from '@angular/forms';
import { ActivatedRoute, Router } from '@angular/router';

import { I18n } from '@ngx-translate/i18n-polyfill';
import * as _ from 'lodash';
import { BsModalRef, BsModalService } from 'ngx-bootstrap/modal';

import { AuthService } from '../../../shared/api/auth.service';
import { RoleService } from '../../../shared/api/role.service';
import { UserService } from '../../../shared/api/user.service';
import { ConfirmationModalComponent } from '../../../shared/components/confirmation-modal/confirmation-modal.component';
import { SelectMessages } from '../../../shared/components/select/select-messages.model';
import { ActionLabelsI18n } from '../../../shared/constants/app.constants';
import { NotificationType } from '../../../shared/enum/notification-type.enum';
import { CdFormGroup } from '../../../shared/forms/cd-form-group';
import { CdValidators } from '../../../shared/forms/cd-validators';
import { AuthStorageService } from '../../../shared/services/auth-storage.service';
import { NotificationService } from '../../../shared/services/notification.service';
import { UserFormMode } from './user-form-mode.enum';
import { UserFormRoleModel } from './user-form-role.model';
import { UserFormModel } from './user-form.model';

@Component({
  selector: 'cd-user-form',
  templateUrl: './user-form.component.html',
  styleUrls: ['./user-form.component.scss']
})
export class UserFormComponent implements OnInit {
  @ViewChild('removeSelfUserReadUpdatePermissionTpl')
  removeSelfUserReadUpdatePermissionTpl: TemplateRef<any>;

  modalRef: BsModalRef;

  userForm: CdFormGroup;
  response: UserFormModel;

  userFormMode = UserFormMode;
  mode: UserFormMode;
  allRoles: Array<UserFormRoleModel>;
  messages = new SelectMessages({ empty: 'There are no roles.' }, this.i18n);
  action: string;
  resource: string;

  constructor(
    private authService: AuthService,
    private authStorageService: AuthStorageService,
    private route: ActivatedRoute,
    private router: Router,
    private modalService: BsModalService,
    private roleService: RoleService,
    private userService: UserService,
    private notificationService: NotificationService,
    private i18n: I18n,
    public actionLabels: ActionLabelsI18n
  ) {
    this.resource = this.i18n('user');
    this.createForm();
    this.messages = new SelectMessages({ empty: 'There are no roles.' }, this.i18n);
  }

  createForm() {
    this.userForm = new CdFormGroup(
      {
        username: new FormControl('', {
          validators: [Validators.required]
        }),
        name: new FormControl(''),
        password: new FormControl('', {
          validators: []
        }),
        confirmpassword: new FormControl('', {
          updateOn: 'blur',
          validators: []
        }),
        email: new FormControl('', {
          validators: [Validators.email]
        }),
        roles: new FormControl([])
      },
      {
        validators: [CdValidators.match('password', 'confirmpassword')]
      }
    );
  }

  ngOnInit() {
    if (this.router.url.startsWith('/user-management/users/edit')) {
      this.mode = this.userFormMode.editing;
      this.action = this.actionLabels.EDIT;
    } else {
      this.action = this.actionLabels.CREATE;
    }

    this.roleService.list().subscribe((roles: Array<UserFormRoleModel>) => {
      this.allRoles = roles;
    });
    if (this.mode === this.userFormMode.editing) {
      this.initEdit();
    }
  }

  initEdit() {
    this.disableForEdit();
    this.route.params.subscribe((params: { username: string }) => {
      const username = params.username;
      this.userService.get(username).subscribe((userFormModel: UserFormModel) => {
        this.response = _.cloneDeep(userFormModel);
        this.setResponse(userFormModel);
      });
    });
  }

  disableForEdit() {
    this.userForm.get('username').disable();
  }

  setResponse(response: UserFormModel) {
    ['username', 'name', 'email', 'roles'].forEach((key) =>
      this.userForm.get(key).setValue(response[key])
    );
  }

  getRequest(): UserFormModel {
    const userFormModel = new UserFormModel();
    ['username', 'password', 'name', 'email', 'roles'].forEach(
      (key) => (userFormModel[key] = this.userForm.get(key).value)
    );
    return userFormModel;
  }

  createAction() {
    const userFormModel = this.getRequest();
    this.userService.create(userFormModel).subscribe(
      () => {
        this.notificationService.show(
          NotificationType.success,
          this.i18n('Created user "{{username}}"', { username: userFormModel.username })
        );
        this.router.navigate(['/user-management/users']);
      },
      () => {
        this.userForm.setErrors({ cdSubmitButton: true });
      }
    );
  }

  editAction() {
    if (this.isUserRemovingNeededRolePermissions()) {
      const initialState = {
        titleText: this.i18n('Update user'),
        buttonText: this.i18n('Continue'),
        bodyTpl: this.removeSelfUserReadUpdatePermissionTpl,
        onSubmit: () => {
          this.modalRef.hide();
          this.doEditAction();
        },
        onCancel: () => {
          this.userForm.setErrors({ cdSubmitButton: true });
          this.userForm.get('roles').reset(this.userForm.get('roles').value);
        }
      };
      this.modalRef = this.modalService.show(ConfirmationModalComponent, { initialState });
    } else {
      this.doEditAction();
    }
  }

  private isCurrentUser(): boolean {
    return this.authStorageService.getUsername() === this.userForm.getValue('username');
  }

  private isUserChangingRoles(): boolean {
    const isCurrentUser = this.isCurrentUser();
    return (
      isCurrentUser &&
      this.response &&
      !_.isEqual(this.response.roles, this.userForm.getValue('roles'))
    );
  }

  private isUserRemovingNeededRolePermissions(): boolean {
    const isCurrentUser = this.isCurrentUser();
    return isCurrentUser && !this.hasUserReadUpdatePermissions(this.userForm.getValue('roles'));
  }

  private hasUserReadUpdatePermissions(roles: Array<string> = []) {
    for (const role of this.allRoles) {
      if (roles.indexOf(role.name) !== -1 && role.scopes_permissions['user']) {
        const userPermissions = role.scopes_permissions['user'];
        return ['read', 'update'].every((permission) => {
          return userPermissions.indexOf(permission) !== -1;
        });
      }
    }
    return false;
  }

  private doEditAction() {
    const userFormModel = this.getRequest();
    this.userService.update(userFormModel).subscribe(
      () => {
        if (this.isUserChangingRoles()) {
          this.authService.logout(() => {
            this.notificationService.show(
              NotificationType.info,
              this.i18n('You were automatically logged out because your roles have been changed.')
            );
          });
        } else {
          this.notificationService.show(
            NotificationType.success,
            this.i18n('Updated user "{{username}}"', { username: userFormModel.username })
          );
          this.router.navigate(['/user-management/users']);
        }
      },
      () => {
        this.userForm.setErrors({ cdSubmitButton: true });
      }
    );
  }

  submit() {
    if (this.mode === this.userFormMode.editing) {
      this.editAction();
    } else {
      this.createAction();
    }
  }
}
<div class="col-sm-12 col-lg-6">
  <form name="userForm"
        class="form-horizontal"
        #formDir="ngForm"
        [formGroup]="userForm"
        novalidate>
    <div class="panel panel-default">
      <div class="panel-heading">
        <h3 i18n="form title|Example: Create Pool@@formTitle"
            class="panel-title">{{ action | titlecase }} {{ resource | upperFirst }}</h3>
      </div>
      <div class="panel-body">

        <!-- Username -->
        <div class="form-group"
             [ngClass]="{'has-error': userForm.showError('username', formDir)}">
          <label class="control-label col-sm-3"
                 for="name">
            <ng-container i18n>Username</ng-container>
            <span class="required"
                  *ngIf="mode !== userFormMode.editing"></span>
          </label>
          <div class="col-sm-9">
            <input class="form-control"
                   type="text"
                   placeholder="Username..."
                   id="username"
                   name="username"
                   formControlName="username"
                   autofocus>
            <span class="help-block"
                  *ngIf="userForm.showError('username', formDir, 'required')"
                  i18n>This field is required.</span>
          </div>
        </div>

        <!-- Password -->
        <div class="form-group"
             [ngClass]="{'has-error': userForm.showError('password', formDir)}">
          <label i18n
                 class="control-label col-sm-3"
                 for="name">Password</label>
          <div class="col-sm-9">
            <div class="input-group">
              <input class="form-control"
                     type="password"
                     placeholder="Password..."
                     id="password"
                     name="password"
                     autocomplete="new-password"
                     formControlName="password">
              <span class="input-group-btn">
                <button type="button"
                        class="btn btn-default"
                        cdPasswordButton="password">
                </button>
              </span>
            </div>
            <span class="help-block"
                  *ngIf="userForm.showError('password', formDir, 'required')"
                  i18n>This field is required.</span>
          </div>
        </div>

        <!-- Confirm password -->
        <div class="form-group"
             [ngClass]="{'has-error': userForm.showError('confirmpassword', formDir)}">
          <label i18n
                 class="control-label col-sm-3"
                 for="name">Confirm password</label>
          <div class="col-sm-9">
            <div class="input-group">
              <input class="form-control"
                     type="password"
                     placeholder="Confirm password..."
                     id="confirmpassword"
                     name="confirmpassword"
                     formControlName="confirmpassword">
              <span class="input-group-btn">
                <button type="button"
                        class="btn btn-default"
                        cdPasswordButton="confirmpassword">
                </button>
              </span>
            </div>
            <span class="help-block"
                  *ngIf="userForm.showError('confirmpassword', formDir, 'required')"
                  i18n>This field is required.</span>
            <span class="help-block"
                  *ngIf="userForm.showError('confirmpassword', formDir, 'match')"
                  i18n>Password confirmation doesn't match the password.</span>
          </div>
        </div>

        <!-- Name -->
        <div class="form-group">
          <label i18n
                 class="control-label col-sm-3"
                 for="name">Full name</label>
          <div class="col-sm-9">
            <input class="form-control"
                   type="text"
                   placeholder="Full name..."
                   id="name"
                   name="name"
                   formControlName="name">
          </div>
        </div>

        <!-- Email -->
        <div class="form-group"
             [ngClass]="{'has-error': userForm.showError('email', formDir)}">
          <label i18n
                 class="control-label col-sm-3"
                 for="email">Email</label>
          <div class="col-sm-9">
            <input class="form-control"
                   type="email"
                   placeholder="Email..."
                   id="email"
                   name="email"
                   formControlName="email">

            <span class="help-block"
                  *ngIf="userForm.showError('email', formDir, 'email')"
                  i18n>Invalid email.</span>
          </div>
        </div>

        <!-- Roles -->
        <label class="col-sm-3 control-label"
               i18n>Roles</label>
        <div class="col-sm-9">
          <span class="form-control no-border full-height"
                *ngIf="allRoles">
            <cd-select-badges [data]="userForm.controls.roles.value"
                              [options]="allRoles"
                              [messages]="messages"></cd-select-badges>
          </span>
        </div>

      </div>
      <div class="panel-footer">
        <div class="button-group text-right">
          <cd-submit-button
            [form]="formDir"
            (submitAction)="submit()"
            i18n="form action button|Example: Create Pool@@formActionButton"
            type="button">{{ action | titlecase }} {{ resource | upperFirst }}</cd-submit-button>
          <cd-back-button></cd-back-button>
        </div>
      </div>
    </div>
  </form>
</div>

<ng-template #removeSelfUserReadUpdatePermissionTpl>
  <p><strong i18n>You are about to remove "user read / update" permissions from your own user.</strong></p>
  <br>
  <p i18n>If you continue, you will no longer be able to add or remove roles from any user.</p>

  <ng-container i18n>Are you sure you want to continue?</ng-container>
</ng-template>

./user-form.component.scss

Legend
Html element
Component
Html element with directive

result-matching ""

    No results matching ""