khairul
7/4/2017 - 12:50 PM

Message Modal for Angular

Message Modal for Angular

import { Injectable } from '@angular/core';
import {Subject} from "rxjs/Subject";

@Injectable()
export class MessageService {

  private messageEventSource = new Subject<{text: string, action: string, link: string, name: string}>();
  messageEventStream = this.messageEventSource.asObservable();

  constructor() { }

  /* send message object to pop-up panel */
  sendMessage(text: string, action?: string, link?: string, name?: string) {
    let message = {
      text: text,
      action: action,
      link: link,
      name: name
    };
    this.messageEventSource.next(message);
  }

}
import {Injectable, OnDestroy} from "@angular/core";
import {Http, Headers, RequestOptions} from "@angular/http";
import 'rxjs/add/operator/catch';
import {Router} from "@angular/router";
import { environment } from '../../environments/environment';
import {CookieService} from "ng2-cookies";
import {MessageService} from "./message.service";

let cr = require('crypto-js');

@Injectable()
export class AuthService implements OnDestroy {

  private I = cr.AES.decrypt(environment.I, 'dstggfh%!').toString(cr.enc.Utf8);
  private S = cr.AES.decrypt(environment.S, 'jgfn@as#').toString(cr.enc.Utf8);
  private domain = environment.domain;
  private isProduction = environment.production;
  private refreshTokenInterval: any;
  public cookieSession = 2*3600*1000; // in [ms]


  constructor(private http: Http,
              private router: Router,
              private cookieService: CookieService,
              private messageService: MessageService
  ) {}

  /* only for localhost testing purposes */
  getAccessToken(role: string) {
    let username = role;
    let password = role;
    let body = 'username=' + username + '&' + 'password=' + password;
    let baseEndPoint = this.domain + '/cos-api/oauth/token?grant_type=password&' + body;
    let basicheader = btoa(this.I + ':' + this.S);

    let headers = new Headers({
      'Authorization': 'Basic '+ basicheader,
      'Accept': 'application/json'
    });

    let options = new RequestOptions({headers: headers});

    return this.http.post(baseEndPoint, '', options).timeout(60000)
      .map((response) => {
        return response.json();
      });
  }

  getUser(tokenData: any) {
    let baseEndPoint = this.domain + '/cos-api/api/user/';
    let headers = new Headers({
      'Authorization': 'Bearer '+ tokenData.access_token,
      'Accept': 'application/json'
    });
    let options = new RequestOptions({headers: headers });

    return this.http.get(baseEndPoint, options)
      .map((response) => {
        return response.json();
      });
  }

  checkAccess(accessToken: string){

    let baseEndPoint = this.domain + '/cos-api/oauth/check_token?token=' + accessToken;

    return this.http.get(baseEndPoint).timeout(60000)
      .map((response) => {
        return response.json();
      });
  }

  autoRefreshAccess(interval: number) {
    this.refreshTokenInterval = setInterval(() => {
      this.refreshAccess();
    }, interval);
  }

  refreshAccess() {

    if(this.cookieService.get('COS_SESSION')) { // check if the cookie is still in the storage

      let refeshToken = (JSON.parse(JSON.parse(this.cookieService.get('COS_SESSION')))).refresh_token;
      let body = '?grant_type=refresh_token&refresh_token=' + refeshToken;
      let baseEndPoint = this.domain + '/cos-api/oauth/token' + body;
      let basicheader = btoa(this.I + ':' + this.S);

      let headers = new Headers({
        'Authorization': 'Basic ' + basicheader,
        'Accept': 'application/json'
      });

      let options = new RequestOptions({headers: headers});

      // refresh access_token
      this.http.post(baseEndPoint, '', options)
        .map((response) => {
          return response.json();
        })
        .subscribe((tokenData) => {
          !this.isProduction && console.log('Token refreshed', tokenData.access_token);
          let cookieMaxAge = new Date((new Date).getTime() + this.cookieSession);
          let cookieValue = JSON.stringify(JSON.stringify(tokenData));
          let cookiePath = '/';
          let cookieDomain = this.isProduction ? this.domain.replace('https://charter', '') : null;

          this.setCookie(cookieValue, cookieMaxAge, cookiePath, cookieDomain, null);

        }, (error) => {
          !this.isProduction && console.warn('Refresh token error: ', error);
          this.cleanlocalData();
          clearInterval(this.refreshTokenInterval);
          /*this.logOut();*/
        });
    }
    else {
      this.cleanlocalData();
      clearInterval(this.refreshTokenInterval);
      this.messageService.sendMessage('session_expired', 'logout');
    }
  }

  isAuthenticated(role: string) {

   if(this.cookieService.get('COS_SESSION')) {
     if(!!localStorage.getItem('userData')) {
       let loggedRole = JSON.parse(localStorage.getItem('userData')).roles;

       if( role === 'AU' && loggedRole.indexOf('CB') > -1 ) { // treat CB as AU role
         return true;
       }
       else {
         return loggedRole.indexOf(role) > -1;
       }
     }
     else {
       return false;
     }
   }
   else {
     /*clearInterval(this.refreshTokenInterval);
     this.cleanlocalData();*/
     /*this.messageService.sendMessage('You are not authorized. Returning to login page.', 'logout');*/
     return false;
   }

   // return true;
  }

  logOut() {

    let baseEndPoint = this.domain + '/c/portal/logout';
    let headers = new Headers({'Accept': 'application/json'});
    let options = new RequestOptions({headers: headers });
    this.cleanlocalData();
    clearInterval(this.refreshTokenInterval);

    this.http.post(baseEndPoint, '', options)
      .subscribe(() => {

        if(this.isProduction) {
          window.location.href = '/';
        }
        else {
          console.log("Logged out!");
          this.removeAllCookies();
          window.location.href = '/';
        }

      }, (error) => {

        if(!this.isProduction) {
          console.warn('Log-out error: ', error);
          this.removeAllCookies();
          window.location.href = '/';
        }
      });
  }

  cleanlocalData() {
    localStorage.removeItem('userData');
  }

  setCookie(value: string, expires: Date, path: string, domain: string, secure: string) {
    !this.isProduction && console.log('Setting new COS_SESSION cookie');

    let cookieStr = 'COS_SESSION' + '=' + value + ';';

    if (expires) {
      cookieStr += 'expires=' + expires.toUTCString() + ';';
    }
    if (path) {
      cookieStr += 'path=' + path + ';';
    }
    if (domain) {
      cookieStr += 'domain=' + domain + ';';
    }
    if (secure) {
      cookieStr += 'secure;';
    }
    document.cookie = cookieStr;
  }

  removeAllCookies() { // to be called only in localhost testing mode
    !this.isProduction && console.log('Removing all cookies');
    this.cookieService.deleteAll();
  }

  ngOnDestroy(): void {
    clearInterval(this.refreshTokenInterval);
  }
}
import {Component, OnDestroy, OnInit, ViewChild} from '@angular/core';
import {ModalDirective, ModalOptions} from "ng2-bootstrap";
import {Subscription} from "rxjs/Subscription";
import {MessageService} from "../../services/message.service";
import {AuthService} from "../../services/auth.service";
declare let $ : any;
@Component({
  selector: 'app-message-modal',
  template: `    
    <div bsModal #smModal="bs-modal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="mySmallModalLabel" aria-hidden="true">
      <div class="modal-dialog modal-sm">
        <div class="modal-content">
          <div class="modal-header">
            <h4 class="modal-title pull-left">Status message</h4>
            <button type="button" class="close pull-right" (click)="onClickAction()" aria-label="Close">
              <span aria-hidden="true">&times;</span>
            </button>
          </div>
          <div class="modal-body">
            <p class="status-message">{{modalText | modalMessage}} <a *ngIf="modalLink" class="message link" [href]="modalLink" target="_blank">here</a></p>
          </div>
          <div class="modal-footer">
            <button class="btn btn-primary" (click)="onClickAction();">OK</button>
          </div>
        </div>
      </div>
    </div> 
  `,
  styles: [`
    .status-message {
        text-align: center;
        margin: 5px 0;
        white-space: pre-line;
    }
  `]
})

export class MessageModalComponent implements OnInit, OnDestroy {

  private messageSubscription: Subscription;
  private modalAction: string;
  private name: string;
  public modalText: string; // text that will be displayed
  public modalLink: string; // optional link

  @ViewChild('smModal') public modal: ModalDirective;

  constructor(private msg: MessageService, private authService: AuthService) {
  }

  ngOnInit() {
    this.modal.config = {
      backdrop: 'static',
      keyboard: false
    };


    this.messageSubscription = this.msg.messageEventStream
      .subscribe((message) => {
        this.modalAction = message.action;
        this.modalLink = message.link;
        this.name = message.name;

        /* if there is any additional name passed (ex. callId or fileName) */
        /* add this name to modal message - it will be later transformed in messageModal pipe*/
        if (this.name) {
          this.modalText = message.text + '$' + this.name;
        }
        else {
          this.modalText = message.text;
        }

        // if there is an action - ignore clicking outside the modal
        this.modal.config.ignoreBackdropClick = !!this.modalAction;
        this.modal.show();

      });
  }

  /* determine the action after user clicks 'OK' or 'x' button */
  onClickAction() {

    /*let timeout = 1300;*/ // set timeout to perform action after modal is closed
    let role = '';

    if (!!localStorage.getItem('userData')) {
      role = JSON.parse(localStorage.getItem('userData')).roles[0].toLowerCase();
    }

    switch(this.modalAction) {
      case 'hide':
        this.modal.hide();
        break;
      case 'reload':
        location.reload();
        break;
      case 'logout':
        this.authService.logOut();
        break;
      case 'nav-main':
        window.location.href = '/';
        break;
      case 'nav-dash':
        window.location.href = '/dashboard/';
        break;
      case 'nav-tasks':
        window.location.href = '?#/' + role + '/my-tasks';
        break;
      case 'nav-details':

        /* take only master call id */
        if (this.name.indexOf('-') > -1) {
          this.name = this.name.split('-')[0];
        }
        window.location.href = '?#/' + role + '/call-details/' + this.name;
        break;
      case 'nav-urf':

        if (this.name) {
          window.location.href = '?#/' + role + '/tmp-call/' + this.name;
        }
        else {
          window.location.href = '?#/' + role + '/tmp-call';
        }
        break;
      default: // also if no action is provided
        this.modal.hide();
    }
  }

  /*ngOnChanges(changes: SimpleChanges): void {
    if(changes['modalMessage'].currentValue) {
      this.modal.show();
    }
  }*/

  ngOnDestroy(): void {
    this.messageSubscription.unsubscribe();
  }

}