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">×</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();
}
}