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 { TranslateService } from '@ngx-translate/core';
26 import { CONSTANTNUMBER, ERRORDATA, GETAPIURLHEADER, PACKAGEINFO, PAGERSMARTTABLE, SMARTTABLECLASS, TARSETTINGS } from 'CommonModel';
27 import { environment } from 'environment';
28 import * as HttpStatus from 'http-status-codes';
29 import * as untar from 'js-untar';
30 import * as pako from 'pako';
31 import { RestService } from 'RestService';
32 import { isNullOrUndefined } from 'util';
34 /** This is added globally by the tar.js library */
35 // tslint:disable-next-line: no-any
36 declare const Tar: any;
39 * An Injectable is a class adorned with the @Injectable decorator function.
40 * @Injectable takes a metadata object that tells Angular how to compile and run module code
45 /** Exporting a class @exports SharedService */
46 export class SharedService {
47 /** call the parent using event information @private */
48 @Output() public dataEvent: EventEmitter<{}> = new EventEmitter<{}>();
50 /** Variables to hold regexp pattern for URL */
51 // tslint:disable-next-line: max-line-length
52 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.,?'\\+&%$#=~_-]+))*$/);
54 /** Variables to hold regexp pattern for IP Address */
55 public REGX_IP_PATTERN: RegExp = new RegExp(/^(?:(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(\.(?!$)|$)){4}$/);
57 /** Variables to hold regexp pattern for Port Number */
58 // tslint:disable-next-line: max-line-length
59 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}))$/);
61 /** Variables to hold regexp pattern for DPID */
62 public REGX_DPID_PATTERN: RegExp = new RegExp(/^[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){7}$/);
64 /** Variable to hold regexp pattern for password */
65 // tslint:disable-next-line: max-line-length
66 public REGX_PASSWORD_PATTERN: RegExp = new RegExp(/^.*(?=.{8,})((?=.*[!@#$%^&*()\-_=+{};:,<.>]){1})(?=.*\d)((?=.*[a-z]){1})((?=.*[A-Z]){1}).*$/);
68 /** Variables to hold maxlength for the description @public */
69 public MAX_LENGTH_DESCRIPTION: number = 500;
71 /** Variables to hold maxlength for the name @public */
72 public MAX_LENGTH_NAME: number = 50;
74 /** FormGroup instance added to the form @ html @public */
75 public formGroup: FormGroup;
77 /** Controls the go to top button on scroll @public */
78 public showGotoTop: boolean;
80 /** Holds OSM Version value @public */
81 public osmVersion: string;
83 /** express number for time manupulation -2 */
84 private epochTimeMinus2: number = -2;
86 /** express number for time manupulation 1000 */
87 private epochTime1000: number = 1000;
89 /** Random string generator length */
90 private randomStringLength: number = 4;
92 /** Instance of the rest service @private */
93 private restService: RestService;
95 /** Service holds the router information @private */
96 private router: Router;
98 /** Random color string generator length @private */
99 private colorStringLength: number = 256;
101 /** Check for the root directory @private */
102 private directoryCount: number = 2;
104 /** Contains tranlsate instance @private */
105 private translateService: TranslateService;
107 constructor(restService: RestService, router: Router, translateService: TranslateService) {
108 this.restService = restService;
109 this.router = router;
110 this.translateService = translateService;
113 /** convert epoch time function @public */
114 public convertEpochTime(unixtimestamp: number): string {
115 if (!isNullOrUndefined(unixtimestamp)) {
116 const monthsArr: string[] = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
117 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
118 const date: Date = new Date(unixtimestamp * this.epochTime1000);
119 const year: number = date.getFullYear();
120 const month: string = monthsArr[date.getMonth()];
121 const day: number = date.getDate();
122 const hours: number = date.getHours();
123 const minutes: string = '0' + date.getMinutes();
124 const seconds: string = '0' + date.getSeconds();
125 return month + '-' + day + '-' + year + ' ' + hours + ':' + minutes.substr(this.epochTimeMinus2) + ':'
126 + seconds.substr(this.epochTimeMinus2);
128 return this.translateService.instant('NODATE');
131 /** Download Files function @public */
132 public downloadFiles(shortName: string, binaryData: Blob[], filetype: string): void {
133 const downloadLink: HTMLAnchorElement = document.createElement('a');
134 downloadLink.href = window.URL.createObjectURL(new Blob(binaryData, { type: filetype }));
135 if (shortName !== undefined) {
136 if (window.navigator.msSaveOrOpenBlob) {
137 window.navigator.msSaveBlob(new Blob(binaryData, { type: filetype }), 'OSM_Export_' + shortName + '.tar.gz');
139 downloadLink.setAttribute('download', 'OSM_Export_' + shortName + '.tar.gz');
140 document.body.appendChild(downloadLink);
141 downloadLink.click();
146 /** Call this method after delete perform action is completed in the ng-smart-table data @public */
147 public callData(): void {
148 this.dataEvent.emit();
151 /** Generate random string @public */
152 public randomString(): string {
153 const chars: string = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
154 let result: string = '';
155 // tslint:disable-next-line:no-increment-decrement
156 for (let randomStringRef: number = this.randomStringLength; randomStringRef > 0; --randomStringRef) {
157 result += chars[Math.floor(Math.random() * chars.length)];
161 /** Function to read uploaded file String @public */
162 public async getFileString(files: FileList, fileType: string): Promise<string | ArrayBuffer> {
163 const reader: FileReader = new FileReader();
164 return new Promise<string | ArrayBuffer>((resolve: Function, reject: Function): void => {
165 if (this.vaildataFileInfo(files[0], fileType)) {
166 this.readFileContent(reader, files[0], fileType);
170 reader.onload = (): void => {
171 if (reader.result === null) {
172 reject('contentError');
174 resolve(reader.result);
176 reader.onerror = (event: Event): void => {
177 reject('contentError');
181 /** Method to handle tar and tar.gz file for shared YAML file content @public */
182 public async targzFile(packageInfo: PACKAGEINFO): Promise<string | ArrayBuffer> {
183 return new Promise<string | ArrayBuffer>((resolve: Function, reject: Function): void => {
184 const httpOptions: GETAPIURLHEADER = this.getHttpOptions();
185 let apiUrl: string = '';
186 apiUrl = packageInfo.packageType === 'nsd' ? environment.NSDESCRIPTORS_URL + '/' + packageInfo.id + '/nsd_content' :
187 environment.VNFPACKAGES_URL + '/' + packageInfo.id + '/package_content';
188 this.restService.getResource(apiUrl, httpOptions).subscribe((response: ArrayBuffer) => {
190 // tslint:disable-next-line: no-any
191 const tar: any = new Tar();
192 const originalInput: Uint8Array = pako.inflate(response, { to: 'Uint8Array' });
193 untar(originalInput.buffer).then((extractedFiles: TARSETTINGS[]) => {
194 const getFoldersFiles: {}[] = extractedFiles;
195 const folderNameStr: string = extractedFiles[0].name;
196 getFoldersFiles.forEach((value: TARSETTINGS) => {
197 const getRootFolder: string[] = value.name.split('/');
198 if (value.name.startsWith(folderNameStr) &&
199 (value.name.endsWith('.yaml') || value.name.endsWith('.yml')) &&
200 getRootFolder.length === this.directoryCount) {
201 tar.append(value.name, packageInfo.descriptor, { type: value.type });
203 if (value.type !== 'L') {
204 tar.append(value.name, new Uint8Array(value.buffer), { type: value.type });
208 const out: Uint8Array = tar.out;
209 const originalOutput: Uint8Array = pako.gzip(out);
210 resolve(originalOutput.buffer);
211 }, (err: string) => {
217 }, (error: HttpErrorResponse) => {
218 if (error.status === HttpStatus.NOT_FOUND || error.status === HttpStatus.UNAUTHORIZED) {
219 this.router.navigateByUrl('404', { skipLocationChange: true }).catch();
221 this.restService.handleError(error, 'get');
227 /** Method to check given string is JSON or not @public */
228 public checkJson(jsonString: string): boolean {
229 jsonString = jsonString.replace(/'/g, '"');
231 JSON.parse(jsonString);
237 /** Clean the form before submit @public */
238 public cleanForm(formGroup: FormGroup, formName?: String): void {
239 Object.keys(formGroup.controls).forEach((key: string) => {
240 if ((!isNullOrUndefined((formGroup.get(key) as FormArray | FormGroup).controls)) && key !== 'config') {
241 // tslint:disable-next-line: no-shadowed-variable
242 for (const { item, index } of (formGroup.get(key).value).map((item: {}, index: number) => ({ item, index }))) {
243 const newFormGroup: FormGroup = (formGroup.get(key) as FormArray).controls[index] as FormGroup;
244 this.cleanForm(newFormGroup);
246 } else if (formGroup.get(key).value !== undefined && formGroup.get(key).value !== null && key !== 'config') {
247 if (!Array.isArray(formGroup.get(key).value)) {
248 if (typeof formGroup.get(key).value === 'string') {
249 formGroup.get(key).setValue(formGroup.get(key).value.trim());
252 } else if (key === 'config' && formName === 'vim') {
253 const newFormGroup: FormGroup = formGroup.get(key) as FormGroup;
254 this.cleanForm(newFormGroup);
258 /** Method to return the config of pager value for ngSmarttable @public */
259 public paginationPagerConfig(): PAGERSMARTTABLE {
262 perPage: environment.paginationNumber
265 /** Method to return the class for the table for ngSmarttable @public */
266 public tableClassConfig(): SMARTTABLECLASS {
268 class: 'table list-data'
271 /** Method to return all languages name and its code @public */
272 public languageCodeList(): {}[] {
274 { code: 'en', language: 'English' },
275 { code: 'es', language: 'Spanish' },
276 { code: 'pt', language: 'Portuguese' },
277 { code: 'de', language: 'German' }
280 /** Fetch OSM Version @public */
281 public fetchOSMVersion(): void {
282 this.restService.getResource(environment.OSM_VERSION_URL).subscribe((res: { version: string }) => {
283 const version: string[] = res.version.split('+');
284 if (!isNullOrUndefined(version[0])) {
285 this.osmVersion = version[0];
287 this.osmVersion = null;
289 }, (error: ERRORDATA) => {
290 this.osmVersion = null;
291 this.restService.handleError(error, 'get');
294 /** Random RGB color code generator @public */
295 public generateColor(): string {
296 const x: number = Math.floor(Math.random() * this.colorStringLength);
297 const y: number = Math.floor(Math.random() * this.colorStringLength);
298 const z: number = Math.floor(Math.random() * this.colorStringLength);
299 return 'rgb(' + x + ',' + y + ',' + z + ')';
302 /** Add custom name/tag to the dropdown @public */
303 public addCustomTag(tag: string): string {
307 /** Fetch file extension @public */
308 public fetchFileExtension(fileInfo: FileList): string {
309 return fileInfo[0].name.substring(fileInfo[0].name.lastIndexOf('.') + 1);
312 /** Method to validate file extension and size @private */
313 private vaildataFileInfo(fileInfo: File, fileType: string): boolean {
314 const extension: string = fileInfo.name.substring(fileInfo.name.lastIndexOf('.') + 1);
315 const packageSize: number = CONSTANTNUMBER.oneMB * environment.packageSize;
316 if (fileType === 'yaml' && (extension.toLowerCase() === 'yaml' || extension.toLowerCase() === 'yml')
317 && fileInfo.size <= packageSize) {
319 } else if (extension.toLowerCase() === fileType && fileInfo.size <= packageSize) {
324 /** Method to read file content based on type @private */
325 private readFileContent(reader: FileReader, fileInfo: File, fileType: string): void {
326 if (fileType === 'gz') {
327 reader.readAsArrayBuffer(fileInfo);
329 reader.readAsText(fileInfo);
332 /** Method to handle http options @public */
333 private getHttpOptions(): GETAPIURLHEADER {
335 headers: new HttpHeaders({
336 Accept: 'application/gzip, application/json',
337 'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0'
339 responseType: 'arraybuffer'