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 /** FormGroup instance added to the form @ html @public */
68 public formGroup: FormGroup;
70 /** Controls the go to top button on scroll @public */
71 public showGotoTop: boolean;
73 /** Holds OSM Version value @public */
74 public osmVersion: string;
76 /** express number for time manupulation -2 */
77 private epochTimeMinus2: number = -2;
79 /** express number for time manupulation 1000 */
80 private epochTime1000: number = 1000;
82 /** Random string generator length */
83 private randomStringLength: number = 4;
85 /** Instance of the rest service @private */
86 private restService: RestService;
88 /** Service holds the router information @private */
89 private router: Router;
91 /** Random color string generator length @private */
92 private colorStringLength: number = 256;
94 /** Check for the root directory @private */
95 private directoryCount: number = 2;
97 constructor(restService: RestService, router: Router) {
98 this.restService = restService;
102 /** convert epoch time function @public */
103 public convertEpochTime(unixtimestamp: number): string {
104 const monthsArr: string[] = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
105 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
106 const date: Date = new Date(unixtimestamp * this.epochTime1000);
107 const year: number = date.getFullYear();
108 const month: string = monthsArr[date.getMonth()];
109 const day: number = date.getDate();
110 const hours: number = date.getHours();
111 const minutes: string = '0' + date.getMinutes();
112 const seconds: string = '0' + date.getSeconds();
113 return month + '-' + day + '-' + year + ' ' + hours + ':' + minutes.substr(this.epochTimeMinus2) + ':'
114 + seconds.substr(this.epochTimeMinus2);
117 /** Download Files function @public */
118 public downloadFiles(shortName: string, binaryData: Blob[], filetype: string): void {
119 const downloadLink: HTMLAnchorElement = document.createElement('a');
120 downloadLink.href = window.URL.createObjectURL(new Blob(binaryData, { type: filetype }));
121 if (shortName !== undefined) {
122 if (window.navigator.msSaveOrOpenBlob) {
123 window.navigator.msSaveBlob(new Blob(binaryData, { type: filetype }), 'OSM_Export_' + shortName + '.tar.gz');
125 downloadLink.setAttribute('download', 'OSM_Export_' + shortName + '.tar.gz');
126 document.body.appendChild(downloadLink);
127 downloadLink.click();
132 /** Call this method after delete perform action is completed in the ng-smart-table data @public */
133 public callData(): void {
134 this.dataEvent.emit();
137 /** Generate random string @public */
138 public randomString(): string {
139 const chars: string = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
140 let result: string = '';
141 // tslint:disable-next-line:no-increment-decrement
142 for (let randomStringRef: number = this.randomStringLength; randomStringRef > 0; --randomStringRef) {
143 result += chars[Math.floor(Math.random() * chars.length)];
147 /** Function to read uploaded file String @public */
148 public async getFileString(files: FileList, fileType: string): Promise<string | ArrayBuffer> {
149 const reader: FileReader = new FileReader();
150 return new Promise<string | ArrayBuffer>((resolve: Function, reject: Function): void => {
151 if (this.vaildataFileInfo(files[0], fileType)) {
152 this.readFileContent(reader, files[0], fileType);
156 reader.onload = (): void => {
157 if (reader.result === null) {
158 reject('contentError');
160 resolve(reader.result);
162 reader.onerror = (event: Event): void => {
163 reject('contentError');
167 /** Method to handle tar and tar.gz file for shared YAML file content @public */
168 public async targzFile(packageInfo: PACKAGEINFO): Promise<string | ArrayBuffer> {
169 return new Promise<string | ArrayBuffer>((resolve: Function, reject: Function): void => {
170 const httpOptions: GETAPIURLHEADER = this.getHttpOptions();
171 let apiUrl: string = '';
172 apiUrl = packageInfo.packageType === 'nsd' ? environment.NSDESCRIPTORS_URL + '/' + packageInfo.id + '/nsd_content' :
173 environment.VNFPACKAGES_URL + '/' + packageInfo.id + '/package_content';
174 this.restService.getResource(apiUrl, httpOptions).subscribe((response: ArrayBuffer) => {
176 // tslint:disable-next-line: no-any
177 const tar: any = new Tar();
178 const originalInput: Uint8Array = pako.inflate(response, { to: 'Uint8Array' });
179 untar(originalInput.buffer).then((extractedFiles: TARSETTINGS[]) => {
180 const getFoldersFiles: {}[] = extractedFiles;
181 const folderNameStr: string = extractedFiles[0].name;
182 getFoldersFiles.forEach((value: TARSETTINGS) => {
183 const getRootFolder: string[] = value.name.split('/');
184 if (value.name.startsWith(folderNameStr) &&
185 (value.name.endsWith('.yaml') || value.name.endsWith('.yml')) &&
186 getRootFolder.length === this.directoryCount) {
187 tar.append(value.name, packageInfo.descriptor, { type: value.type });
189 if (value.type !== 'L') {
190 tar.append(value.name, new Uint8Array(value.buffer), { type: value.type });
194 const out: Uint8Array = tar.out;
195 const originalOutput: Uint8Array = pako.gzip(out);
196 resolve(originalOutput.buffer);
197 }, (err: string) => {
203 }, (error: HttpErrorResponse) => {
204 if (error.status === HttpStatus.NOT_FOUND || error.status === HttpStatus.UNAUTHORIZED) {
205 this.router.navigateByUrl('404', { skipLocationChange: true }).catch();
207 this.restService.handleError(error, 'get');
213 /** Method to check given string is JSON or not @public */
214 public checkJson(jsonString: string): boolean {
215 jsonString = jsonString.replace(/'/g, '"');
217 JSON.parse(jsonString);
223 /** Clean the form before submit @public */
224 public cleanForm(formGroup: FormGroup, formName?: String): void {
225 Object.keys(formGroup.controls).forEach((key: string) => {
226 if ((!isNullOrUndefined((formGroup.get(key) as FormArray | FormGroup).controls)) && key !== 'config') {
227 // tslint:disable-next-line: no-shadowed-variable
228 for (const { item, index } of (formGroup.get(key).value).map((item: {}, index: number) => ({ item, index }))) {
229 const newFormGroup: FormGroup = (formGroup.get(key) as FormArray).controls[index] as FormGroup;
230 this.cleanForm(newFormGroup);
232 } else if (formGroup.get(key).value !== undefined && formGroup.get(key).value !== null && key !== 'config') {
233 if (!Array.isArray(formGroup.get(key).value)) {
234 if (typeof formGroup.get(key).value === 'string') {
235 formGroup.get(key).setValue(formGroup.get(key).value.trim());
238 } else if (key === 'config' && formName === 'vim') {
239 const newFormGroup: FormGroup = formGroup.get(key) as FormGroup;
240 this.cleanForm(newFormGroup);
244 /** Method to return the config of pager value for ngSmarttable @public */
245 public paginationPagerConfig(): PAGERSMARTTABLE {
248 perPage: environment.paginationNumber
251 /** Method to return the class for the table for ngSmarttable @public */
252 public tableClassConfig(): SMARTTABLECLASS {
254 class: 'table list-data'
257 /** Method to return all languages name and its code @public */
258 public languageCodeList(): {}[] {
260 { code: 'en', language: 'English' },
261 { code: 'es', language: 'Spanish' },
262 { code: 'pt', language: 'Portuguese' },
263 { code: 'de', language: 'German' }
266 /** Fetch OSM Version @public */
267 public fetchOSMVersion(): void {
268 this.restService.getResource(environment.OSM_VERSION_URL).subscribe((res: { version: string }) => {
269 const version: string[] = res.version.split('+');
270 if (!isNullOrUndefined(version[0])) {
271 this.osmVersion = version[0];
273 this.osmVersion = null;
275 }, (error: ERRORDATA) => {
276 this.osmVersion = null;
277 this.restService.handleError(error, 'get');
280 /** Random RGB color code generator @public */
281 public generateColor(): string {
282 const x: number = Math.floor(Math.random() * this.colorStringLength);
283 const y: number = Math.floor(Math.random() * this.colorStringLength);
284 const z: number = Math.floor(Math.random() * this.colorStringLength);
285 return 'rgb(' + x + ',' + y + ',' + z + ')';
288 /** Add custom name/tag to the dropdown @public */
289 public addCustomTag(tag: string): string {
293 /** Method to validate file extension and size @private */
294 private vaildataFileInfo(fileInfo: File, fileType: string): boolean {
295 const extension: string = fileInfo.name.substring(fileInfo.name.lastIndexOf('.') + 1);
296 const packageSize: number = CONSTANTNUMBER.oneMB * environment.packageSize;
297 if (fileType === 'yaml' && (extension.toLowerCase() === 'yaml' || extension.toLowerCase() === 'yml')
298 && fileInfo.size <= packageSize) {
300 } else if (extension.toLowerCase() === fileType && fileInfo.size <= packageSize) {
305 /** Method to read file content based on type @private */
306 private readFileContent(reader: FileReader, fileInfo: File, fileType: string): void {
307 if (fileType === 'gz') {
308 reader.readAsArrayBuffer(fileInfo);
310 reader.readAsText(fileInfo);
313 /** Method to handle http options @public */
314 private getHttpOptions(): GETAPIURLHEADER {
316 headers: new HttpHeaders({
317 Accept: 'application/gzip, application/json',
318 'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0'
320 responseType: 'arraybuffer'