2 Copyright 2020 TATA ELXSI
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
8 http://www.apache.org/licenses/LICENSE-2.0
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.
16 Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
19 * @file Provider for Shared Service
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';
33 /** This is added globally by the tar.js library */
34 // tslint:disable-next-line: no-any
35 declare const Tar: any;
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
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<{}>();
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.,?'\\+&%$#=~_-]+))*$/);
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}$/);
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}))$/);
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}$/);
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}).*$/);
67 /** Variables to hold maxlength for the description @public */
68 public MAX_LENGTH_DESCRIPTION: number = 500;
70 /** Variables to hold maxlength for the name @public */
71 public MAX_LENGTH_NAME: number = 50;
73 /** FormGroup instance added to the form @ html @public */
74 public formGroup: FormGroup;
76 /** Controls the go to top button on scroll @public */
77 public showGotoTop: boolean;
79 /** Holds OSM Version value @public */
80 public osmVersion: string;
82 /** express number for time manupulation -2 */
83 private epochTimeMinus2: number = -2;
85 /** express number for time manupulation 1000 */
86 private epochTime1000: number = 1000;
88 /** Random string generator length */
89 private randomStringLength: number = 4;
91 /** Instance of the rest service @private */
92 private restService: RestService;
94 /** Service holds the router information @private */
95 private router: Router;
97 /** Random color string generator length @private */
98 private colorStringLength: number = 256;
100 /** Check for the root directory @private */
101 private directoryCount: number = 2;
103 constructor(restService: RestService, router: Router) {
104 this.restService = restService;
105 this.router = router;
108 /** convert epoch time function @public */
109 public convertEpochTime(unixtimestamp: number): string {
110 const monthsArr: string[] = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
111 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
112 const date: Date = new Date(unixtimestamp * this.epochTime1000);
113 const year: number = date.getFullYear();
114 const month: string = monthsArr[date.getMonth()];
115 const day: number = date.getDate();
116 const hours: number = date.getHours();
117 const minutes: string = '0' + date.getMinutes();
118 const seconds: string = '0' + date.getSeconds();
119 return month + '-' + day + '-' + year + ' ' + hours + ':' + minutes.substr(this.epochTimeMinus2) + ':'
120 + seconds.substr(this.epochTimeMinus2);
123 /** Download Files function @public */
124 public downloadFiles(shortName: string, binaryData: Blob[], filetype: string): void {
125 const downloadLink: HTMLAnchorElement = document.createElement('a');
126 downloadLink.href = window.URL.createObjectURL(new Blob(binaryData, { type: filetype }));
127 if (shortName !== undefined) {
128 if (window.navigator.msSaveOrOpenBlob) {
129 window.navigator.msSaveBlob(new Blob(binaryData, { type: filetype }), 'OSM_Export_' + shortName + '.tar.gz');
131 downloadLink.setAttribute('download', 'OSM_Export_' + shortName + '.tar.gz');
132 document.body.appendChild(downloadLink);
133 downloadLink.click();
138 /** Call this method after delete perform action is completed in the ng-smart-table data @public */
139 public callData(): void {
140 this.dataEvent.emit();
143 /** Generate random string @public */
144 public randomString(): string {
145 const chars: string = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
146 let result: string = '';
147 // tslint:disable-next-line:no-increment-decrement
148 for (let randomStringRef: number = this.randomStringLength; randomStringRef > 0; --randomStringRef) {
149 result += chars[Math.floor(Math.random() * chars.length)];
153 /** Function to read uploaded file String @public */
154 public async getFileString(files: FileList, fileType: string): Promise<string | ArrayBuffer> {
155 const reader: FileReader = new FileReader();
156 return new Promise<string | ArrayBuffer>((resolve: Function, reject: Function): void => {
157 if (this.vaildataFileInfo(files[0], fileType)) {
158 this.readFileContent(reader, files[0], fileType);
162 reader.onload = (): void => {
163 if (reader.result === null) {
164 reject('contentError');
166 resolve(reader.result);
168 reader.onerror = (event: Event): void => {
169 reject('contentError');
173 /** Method to handle tar and tar.gz file for shared YAML file content @public */
174 public async targzFile(packageInfo: PACKAGEINFO): Promise<string | ArrayBuffer> {
175 return new Promise<string | ArrayBuffer>((resolve: Function, reject: Function): void => {
176 const httpOptions: GETAPIURLHEADER = this.getHttpOptions();
177 let apiUrl: string = '';
178 apiUrl = packageInfo.packageType === 'nsd' ? environment.NSDESCRIPTORS_URL + '/' + packageInfo.id + '/nsd_content' :
179 environment.VNFPACKAGES_URL + '/' + packageInfo.id + '/package_content';
180 this.restService.getResource(apiUrl, httpOptions).subscribe((response: ArrayBuffer) => {
182 // tslint:disable-next-line: no-any
183 const tar: any = new Tar();
184 const originalInput: Uint8Array = pako.inflate(response, { to: 'Uint8Array' });
185 untar(originalInput.buffer).then((extractedFiles: TARSETTINGS[]) => {
186 const getFoldersFiles: {}[] = extractedFiles;
187 const folderNameStr: string = extractedFiles[0].name;
188 getFoldersFiles.forEach((value: TARSETTINGS) => {
189 const getRootFolder: string[] = value.name.split('/');
190 if (value.name.startsWith(folderNameStr) &&
191 (value.name.endsWith('.yaml') || value.name.endsWith('.yml')) &&
192 getRootFolder.length === this.directoryCount) {
193 tar.append(value.name, packageInfo.descriptor, { type: value.type });
195 if (value.type !== 'L') {
196 tar.append(value.name, new Uint8Array(value.buffer), { type: value.type });
200 const out: Uint8Array = tar.out;
201 const originalOutput: Uint8Array = pako.gzip(out);
202 resolve(originalOutput.buffer);
203 }, (err: string) => {
209 }, (error: HttpErrorResponse) => {
210 if (error.status === HttpStatus.NOT_FOUND || error.status === HttpStatus.UNAUTHORIZED) {
211 this.router.navigateByUrl('404', { skipLocationChange: true }).catch();
213 this.restService.handleError(error, 'get');
219 /** Method to check given string is JSON or not @public */
220 public checkJson(jsonString: string): boolean {
221 jsonString = jsonString.replace(/'/g, '"');
223 JSON.parse(jsonString);
229 /** Clean the form before submit @public */
230 public cleanForm(formGroup: FormGroup, formName?: String): void {
231 Object.keys(formGroup.controls).forEach((key: string) => {
232 if ((!isNullOrUndefined((formGroup.get(key) as FormArray | FormGroup).controls)) && key !== 'config') {
233 // tslint:disable-next-line: no-shadowed-variable
234 for (const { item, index } of (formGroup.get(key).value).map((item: {}, index: number) => ({ item, index }))) {
235 const newFormGroup: FormGroup = (formGroup.get(key) as FormArray).controls[index] as FormGroup;
236 this.cleanForm(newFormGroup);
238 } else if (formGroup.get(key).value !== undefined && formGroup.get(key).value !== null && key !== 'config') {
239 if (!Array.isArray(formGroup.get(key).value)) {
240 if (typeof formGroup.get(key).value === 'string') {
241 formGroup.get(key).setValue(formGroup.get(key).value.trim());
244 } else if (key === 'config' && formName === 'vim') {
245 const newFormGroup: FormGroup = formGroup.get(key) as FormGroup;
246 this.cleanForm(newFormGroup);
250 /** Method to return the config of pager value for ngSmarttable @public */
251 public paginationPagerConfig(): PAGERSMARTTABLE {
254 perPage: environment.paginationNumber
257 /** Method to return the class for the table for ngSmarttable @public */
258 public tableClassConfig(): SMARTTABLECLASS {
260 class: 'table list-data'
263 /** Method to return all languages name and its code @public */
264 public languageCodeList(): {}[] {
266 { code: 'en', language: 'English' },
267 { code: 'es', language: 'Spanish' },
268 { code: 'pt', language: 'Portuguese' },
269 { code: 'de', language: 'German' }
272 /** Fetch OSM Version @public */
273 public fetchOSMVersion(): void {
274 this.restService.getResource(environment.OSM_VERSION_URL).subscribe((res: { version: string }) => {
275 const version: string[] = res.version.split('+');
276 if (!isNullOrUndefined(version[0])) {
277 this.osmVersion = version[0];
279 this.osmVersion = null;
281 }, (error: ERRORDATA) => {
282 this.osmVersion = null;
283 this.restService.handleError(error, 'get');
286 /** Random RGB color code generator @public */
287 public generateColor(): string {
288 const x: number = Math.floor(Math.random() * this.colorStringLength);
289 const y: number = Math.floor(Math.random() * this.colorStringLength);
290 const z: number = Math.floor(Math.random() * this.colorStringLength);
291 return 'rgb(' + x + ',' + y + ',' + z + ')';
294 /** Add custom name/tag to the dropdown @public */
295 public addCustomTag(tag: string): string {
299 /** Method to validate file extension and size @private */
300 private vaildataFileInfo(fileInfo: File, fileType: string): boolean {
301 const extension: string = fileInfo.name.substring(fileInfo.name.lastIndexOf('.') + 1);
302 const packageSize: number = CONSTANTNUMBER.oneMB * environment.packageSize;
303 if (fileType === 'yaml' && (extension.toLowerCase() === 'yaml' || extension.toLowerCase() === 'yml')
304 && fileInfo.size <= packageSize) {
306 } else if (extension.toLowerCase() === fileType && fileInfo.size <= packageSize) {
311 /** Method to read file content based on type @private */
312 private readFileContent(reader: FileReader, fileInfo: File, fileType: string): void {
313 if (fileType === 'gz') {
314 reader.readAsArrayBuffer(fileInfo);
316 reader.readAsText(fileInfo);
319 /** Method to handle http options @public */
320 private getHttpOptions(): GETAPIURLHEADER {
322 headers: new HttpHeaders({
323 Accept: 'application/gzip, application/json',
324 'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0'
326 responseType: 'arraybuffer'