3a138e585a54563823330fee8bb660e3f60d05bd
[osm/NG-UI.git] / src / services / SharedService.ts
1 /*
2  Copyright 2020 TATA ELXSI
3
4  Licensed under the Apache License, Version 2.0 (the 'License');
5  you may not use this file except in compliance with the License.
6  You may obtain a copy of the License at
7
8     http://www.apache.org/licenses/LICENSE-2.0
9
10  Unless required by applicable law or agreed to in writing, software
11  distributed under the License is distributed on an "AS IS" BASIS,
12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  See the License for the specific language governing permissions and
14  limitations under the License.
15
16  Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
17  */
18 /**
19  * @file Provider for Shared Service
20  */
21 import { HttpErrorResponse, HttpHeaders } from '@angular/common/http';
22 import { EventEmitter, Injectable, Output } from '@angular/core';
23 import { FormArray, FormGroup } from '@angular/forms';
24 import { Router } from '@angular/router';
25 import { CONSTANTNUMBER, ERRORDATA, GETAPIURLHEADER, PACKAGEINFO, PAGERSMARTTABLE, SMARTTABLECLASS, TARSETTINGS } from 'CommonModel';
26 import { environment } from 'environment';
27 import * as HttpStatus from 'http-status-codes';
28 import * as untar from 'js-untar';
29 import * as pako from 'pako';
30 import { RestService } from 'RestService';
31 import { isNullOrUndefined } from 'util';
32
33 /** This is added globally by the tar.js library */
34 // tslint:disable-next-line: no-any
35 declare const Tar: any;
36
37 /**
38  * An Injectable is a class adorned with the @Injectable decorator function.
39  * @Injectable takes a metadata object that tells Angular how to compile and run module code
40  */
41 @Injectable({
42     providedIn: 'root'
43 })
44 /** Exporting a class @exports SharedService */
45 export class SharedService {
46     /** call the parent using event information @private */
47     @Output() public dataEvent: EventEmitter<{}> = new EventEmitter<{}>();
48
49     /** Variables to hold regexp pattern for URL */
50     // tslint:disable-next-line: max-line-length
51     public REGX_URL_PATTERN: RegExp = new RegExp(/^(http?|ftp|https):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.[a-zA-Z0-9]{2,15})(:((6553[0-5])|(655[0-2][0-9])|(65[0-4][0-9]{2})|(6[0-4][0-9]{3})|([1-5][0-9]{4})|([0-5]{0,5})|([0-9]{1,4})))*(\/($|[a-zA-Z0-9.,?'\\+&%$#=~_-]+))*$/);
52
53     /** Variables to hold regexp pattern for IP Address */
54     public REGX_IP_PATTERN: RegExp = new RegExp(/^(?:(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(\.(?!$)|$)){4}$/);
55
56     /** Variables to hold regexp pattern for Port Number */
57     // tslint:disable-next-line: max-line-length
58     public REGX_PORT_PATTERN: RegExp = new RegExp(/^((6553[0-5])|(655[0-2][0-9])|(65[0-4][0-9]{2})|(6[0-4][0-9]{3})|([1-5][0-9]{4})|([0-5]{0,5})|([0-9]{1,4}))$/);
59
60     /** Variables to hold regexp pattern for DPID */
61     public REGX_DPID_PATTERN: RegExp = new RegExp(/^[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){7}$/);
62
63     /** Variable to hold regexp pattern for password */
64     // tslint:disable-next-line: max-line-length
65     public REGX_PASSWORD_PATTERN: RegExp = new RegExp(/^.*(?=.{8,})((?=.*[!@#$%^&*()\-_=+{};:,<.>]){1})(?=.*\d)((?=.*[a-z]){1})((?=.*[A-Z]){1}).*$/);
66
67     /** FormGroup instance added to the form @ html @public */
68     public formGroup: FormGroup;
69
70     /** Controls the go to top button on scroll  @public */
71     public showGotoTop: boolean;
72
73     /** Holds OSM Version value @public */
74     public osmVersion: string;
75
76     /** express number for time manupulation -2 */
77     private epochTimeMinus2: number = -2;
78
79     /** express number for time manupulation 1000 */
80     private epochTime1000: number = 1000;
81
82     /** Random string generator length */
83     private randomStringLength: number = 4;
84
85     /** Instance of the rest service @private */
86     private restService: RestService;
87
88     /** Service holds the router information @private */
89     private router: Router;
90
91     /** Check for the root directory @private */
92     private directoryCount: number = 2;
93
94     constructor(restService: RestService, router: Router) {
95         this.restService = restService;
96         this.router = router;
97     }
98
99     /** convert epoch time function @public */
100     public convertEpochTime(unixtimestamp: number): string {
101         const monthsArr: string[] = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
102             'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
103         const date: Date = new Date(unixtimestamp * this.epochTime1000);
104         const year: number = date.getFullYear();
105         const month: string = monthsArr[date.getMonth()];
106         const day: number = date.getDate();
107         const hours: number = date.getHours();
108         const minutes: string = '0' + date.getMinutes();
109         const seconds: string = '0' + date.getSeconds();
110         return month + '-' + day + '-' + year + ' ' + hours + ':' + minutes.substr(this.epochTimeMinus2) + ':'
111             + seconds.substr(this.epochTimeMinus2);
112     }
113
114     /** Download Files function @public */
115     public downloadFiles(shortName: string, binaryData: Blob[], filetype: string): void {
116         const downloadLink: HTMLAnchorElement = document.createElement('a');
117         downloadLink.href = window.URL.createObjectURL(new Blob(binaryData, { type: filetype }));
118         if (shortName !== undefined) {
119             if (window.navigator.msSaveOrOpenBlob) {
120                 window.navigator.msSaveBlob(new Blob(binaryData, { type: filetype }), 'OSM_Export_' + shortName + '.tar.gz');
121             } else {
122                 downloadLink.setAttribute('download', 'OSM_Export_' + shortName + '.tar.gz');
123                 document.body.appendChild(downloadLink);
124                 downloadLink.click();
125             }
126         }
127     }
128
129     /** Call this method after delete perform action is completed in the ng-smart-table data @public */
130     public callData(): void {
131         this.dataEvent.emit();
132     }
133
134     /** Generate random string @public */
135     public randomString(): string {
136         const chars: string = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
137         let result: string = '';
138         // tslint:disable-next-line:no-increment-decrement
139         for (let randomStringRef: number = this.randomStringLength; randomStringRef > 0; --randomStringRef) {
140             result += chars[Math.floor(Math.random() * chars.length)];
141         }
142         return result;
143     }
144     /** Function to read uploaded file String @public */
145     public async getFileString(files: FileList, fileType: string): Promise<string | ArrayBuffer> {
146         const reader: FileReader = new FileReader();
147         return new Promise<string | ArrayBuffer>((resolve: Function, reject: Function): void => {
148             if (this.vaildataFileInfo(files[0], fileType)) {
149                 this.readFileContent(reader, files[0], fileType);
150             } else {
151                 reject('typeError');
152             }
153             reader.onload = (): void => {
154                 if (reader.result === null) {
155                     reject('contentError');
156                 }
157                 resolve(reader.result);
158             };
159             reader.onerror = (event: Event): void => {
160                 reject('contentError');
161             };
162         });
163     }
164     /** Method to handle tar and tar.gz file for shared YAML file content @public */
165     public async targzFile(packageInfo: PACKAGEINFO): Promise<string | ArrayBuffer> {
166         return new Promise<string | ArrayBuffer>((resolve: Function, reject: Function): void => {
167             const httpOptions: GETAPIURLHEADER = this.getHttpOptions();
168             let apiUrl: string = '';
169             apiUrl = packageInfo.packageType === 'nsd' ? environment.NSDESCRIPTORS_URL + '/' + packageInfo.id + '/nsd_content' :
170                 environment.VNFPACKAGES_URL + '/' + packageInfo.id + '/package_content';
171             this.restService.getResource(apiUrl, httpOptions).subscribe((response: ArrayBuffer) => {
172                 try {
173                     // tslint:disable-next-line: no-any
174                     const tar: any = new Tar();
175                     const originalInput: Uint8Array = pako.inflate(response, { to: 'Uint8Array' });
176                     untar(originalInput.buffer).then((extractedFiles: TARSETTINGS[]) => {
177                         const getFoldersFiles: {}[] = extractedFiles;
178                         const folderNameStr: string = extractedFiles[0].name;
179                         getFoldersFiles.forEach((value: TARSETTINGS) => {
180                             const getRootFolder: string[] = value.name.split('/');
181                             if (value.name.startsWith(folderNameStr) &&
182                                 (value.name.endsWith('.yaml') || value.name.endsWith('.yml')) &&
183                                 getRootFolder.length === this.directoryCount) {
184                                 tar.append(value.name, packageInfo.descriptor, { type: value.type });
185                             } else {
186                                 if (value.type !== 'L') {
187                                     tar.append(value.name, new Uint8Array(value.buffer), { type: value.type });
188                                 }
189                             }
190                         });
191                         const out: Uint8Array = tar.out;
192                         const originalOutput: Uint8Array = pako.gzip(out);
193                         resolve(originalOutput.buffer);
194                     }, (err: string) => {
195                         reject('');
196                     });
197                 } catch (e) {
198                     reject('');
199                 }
200             }, (error: HttpErrorResponse) => {
201                 if (error.status === HttpStatus.NOT_FOUND || error.status === HttpStatus.UNAUTHORIZED) {
202                     this.router.navigateByUrl('404', { skipLocationChange: true }).catch();
203                 } else {
204                     this.restService.handleError(error, 'get');
205                     reject('');
206                 }
207             });
208         });
209     }
210     /** Method to check given string is JSON or not @public */
211     public checkJson(jsonString: string): boolean {
212         jsonString = jsonString.replace(/'/g, '"');
213         try {
214             JSON.parse(jsonString);
215         } catch (e) {
216             return false;
217         }
218         return true;
219     }
220     /** Clean the form before submit @public */
221     public cleanForm(formGroup: FormGroup): void {
222         Object.keys(formGroup.controls).forEach((key: string) => {
223             if ((!isNullOrUndefined((formGroup.get(key) as FormArray | FormGroup).controls)) && key !== 'vimconfig') {
224                 // tslint:disable-next-line: no-shadowed-variable
225                 for (const { item, index } of (formGroup.get(key).value).map((item: {}, index: number) => ({ item, index }))) {
226                     const newFormGroup: FormGroup = (formGroup.get(key) as FormArray).controls[index] as FormGroup;
227                     this.cleanForm(newFormGroup);
228                 }
229             } else if (formGroup.get(key).value !== undefined && formGroup.get(key).value !== null && key !== 'vimconfig') {
230                 if (!Array.isArray(formGroup.get(key).value)) {
231                     if (typeof formGroup.get(key).value === 'string') {
232                         formGroup.get(key).setValue(formGroup.get(key).value.trim());
233                     }
234                 }
235             } else if (key === 'vimconfig') {
236                 const newFormGroup: FormGroup = formGroup.get(key) as FormGroup;
237                 this.cleanForm(newFormGroup);
238             }
239         });
240     }
241     /** Method to return the config of pager value for ngSmarttable @public */
242     public paginationPagerConfig(): PAGERSMARTTABLE {
243         return {
244             display: true,
245             perPage: environment.paginationNumber
246         };
247     }
248     /** Method to return the class for the table for ngSmarttable @public */
249     public tableClassConfig(): SMARTTABLECLASS {
250         return {
251             class: 'table list-data'
252         };
253     }
254     /** Method to return all languages name and its code @public */
255     public languageCodeList(): {}[] {
256         return [
257             { code: 'en', language: 'English' },
258             { code: 'es', language: 'Spanish' },
259             { code: 'pt', language: 'Portuguese' },
260             { code: 'de', language: 'German' }
261         ];
262     }
263     /** Fetch OSM Version @public */
264     public fetchOSMVersion(): void {
265         this.restService.getResource(environment.OSM_VERSION_URL).subscribe((res: { version: string }) => {
266             const version: string[] = res.version.split('+');
267             if (!isNullOrUndefined(version[0])) {
268                 this.osmVersion = version[0];
269             } else {
270                 this.osmVersion = null;
271             }
272         }, (error: ERRORDATA) => {
273             this.osmVersion = null;
274             this.restService.handleError(error, 'get');
275         });
276     }
277     /** Method to validate file extension and size @private */
278     private vaildataFileInfo(fileInfo: File, fileType: string): boolean {
279         const extension: string = fileInfo.name.substring(fileInfo.name.lastIndexOf('.') + 1);
280         const packageSize: number = CONSTANTNUMBER.oneMB * environment.packageSize;
281         if (extension.toLowerCase() === fileType && fileInfo.size <= packageSize) {
282             return true;
283         }
284         return false;
285     }
286     /** Method to read file content based on type @private */
287     private readFileContent(reader: FileReader, fileInfo: File, fileType: string): void {
288         if (fileType === 'gz') {
289             reader.readAsArrayBuffer(fileInfo);
290         } else {
291             reader.readAsText(fileInfo);
292         }
293     }
294     /** Method to handle http options @public */
295     private getHttpOptions(): GETAPIURLHEADER {
296         return {
297             headers: new HttpHeaders({
298                 Accept: 'application/gzip, application/json',
299                 'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0'
300             }),
301             responseType: 'arraybuffer'
302         };
303     }
304 }