--- /dev/null
+/*
+ Copyright 2020 TATA ELXSI
+
+ Licensed under the Apache License, Version 2.0 (the 'License');
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ Author: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
+ */
+/**
+ * @file Provider for Shared Service
+ */
+import { HttpErrorResponse, HttpHeaders } from '@angular/common/http';
+import { EventEmitter, Injectable, Output } from '@angular/core';
+import { FormArray, FormGroup } from '@angular/forms';
+import { Router } from '@angular/router';
+import { CONSTANTNUMBER, ERRORDATA, GETAPIURLHEADER, PACKAGEINFO, PAGERSMARTTABLE, SMARTTABLECLASS, TARSETTINGS } from 'CommonModel';
+import { environment } from 'environment';
+import * as HttpStatus from 'http-status-codes';
+import * as untar from 'js-untar';
+import * as pako from 'pako';
+import { RestService } from 'RestService';
+import { isNullOrUndefined } from 'util';
+
+/** This is added globally by the tar.js library */
+// tslint:disable-next-line: no-any
+declare const Tar: any;
+
+/**
+ * An Injectable is a class adorned with the @Injectable decorator function.
+ * @Injectable takes a metadata object that tells Angular how to compile and run module code
+ */
+@Injectable({
+ providedIn: 'root'
+})
+/** Exporting a class @exports SharedService */
+export class SharedService {
+ /** call the parent using event information @private */
+ @Output() public dataEvent: EventEmitter<{}> = new EventEmitter<{}>();
+
+ /** Variables to hold regexp pattern for URL */
+ // tslint:disable-next-line: max-line-length
+ 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.,?'\\+&%$#=~_-]+))*$/);
+
+ /** Variables to hold regexp pattern for IP Address */
+ public REGX_IP_PATTERN: RegExp = new RegExp(/^(?:(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(\.(?!$)|$)){4}$/);
+
+ /** Variables to hold regexp pattern for Port Number */
+ // tslint:disable-next-line: max-line-length
+ 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}))$/);
+
+ /** Variables to hold regexp pattern for DPID */
+ public REGX_DPID_PATTERN: RegExp = new RegExp(/^[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){7}$/);
+
+ /** Variable to hold regexp pattern for password */
+ // tslint:disable-next-line: max-line-length
+ public REGX_PASSWORD_PATTERN: RegExp = new RegExp(/^.*(?=.{8,})((?=.*[!@#$%^&*()\-_=+{};:,<.>]){1})(?=.*\d)((?=.*[a-z]){1})((?=.*[A-Z]){1}).*$/);
+
+ /** FormGroup instance added to the form @ html @public */
+ public formGroup: FormGroup;
+
+ /** Controls the go to top button on scroll @public */
+ public showGotoTop: boolean;
+
+ /** Holds OSM Version value @public */
+ public osmVersion: string;
+
+ /** express number for time manupulation -2 */
+ private epochTimeMinus2: number = -2;
+
+ /** express number for time manupulation 1000 */
+ private epochTime1000: number = 1000;
+
+ /** Random string generator length */
+ private randomStringLength: number = 4;
+
+ /** Instance of the rest service @private */
+ private restService: RestService;
+
+ /** Service holds the router information @private */
+ private router: Router;
+
+ /** Check for the root directory @private */
+ private directoryCount: number = 2;
+
+ constructor(restService: RestService, router: Router) {
+ this.restService = restService;
+ this.router = router;
+ }
+
+ /** convert epoch time function @public */
+ public convertEpochTime(unixtimestamp: number): string {
+ const monthsArr: string[] = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
+ 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
+ const date: Date = new Date(unixtimestamp * this.epochTime1000);
+ const year: number = date.getFullYear();
+ const month: string = monthsArr[date.getMonth()];
+ const day: number = date.getDate();
+ const hours: number = date.getHours();
+ const minutes: string = '0' + date.getMinutes();
+ const seconds: string = '0' + date.getSeconds();
+ return month + '-' + day + '-' + year + ' ' + hours + ':' + minutes.substr(this.epochTimeMinus2) + ':'
+ + seconds.substr(this.epochTimeMinus2);
+ }
+
+ /** Download Files function @public */
+ public downloadFiles(shortName: string, binaryData: Blob[], filetype: string): void {
+ const downloadLink: HTMLAnchorElement = document.createElement('a');
+ downloadLink.href = window.URL.createObjectURL(new Blob(binaryData, { type: filetype }));
+ if (shortName !== undefined) {
+ if (window.navigator.msSaveOrOpenBlob) {
+ window.navigator.msSaveBlob(new Blob(binaryData, { type: filetype }), 'OSM_Export_' + shortName + '.tar.gz');
+ } else {
+ downloadLink.setAttribute('download', 'OSM_Export_' + shortName + '.tar.gz');
+ document.body.appendChild(downloadLink);
+ downloadLink.click();
+ }
+ }
+ }
+
+ /** Call this method after delete perform action is completed in the ng-smart-table data @public */
+ public callData(): void {
+ this.dataEvent.emit();
+ }
+
+ /** Generate random string @public */
+ public randomString(): string {
+ const chars: string = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
+ let result: string = '';
+ // tslint:disable-next-line:no-increment-decrement
+ for (let randomStringRef: number = this.randomStringLength; randomStringRef > 0; --randomStringRef) {
+ result += chars[Math.floor(Math.random() * chars.length)];
+ }
+ return result;
+ }
+ /** Function to read uploaded file String @public */
+ public async getFileString(files: FileList, fileType: string): Promise<string | ArrayBuffer> {
+ const reader: FileReader = new FileReader();
+ return new Promise<string | ArrayBuffer>((resolve: Function, reject: Function): void => {
+ if (this.vaildataFileInfo(files[0], fileType)) {
+ this.readFileContent(reader, files[0], fileType);
+ } else {
+ reject('typeError');
+ }
+ reader.onload = (): void => {
+ if (reader.result === null) {
+ reject('contentError');
+ }
+ resolve(reader.result);
+ };
+ reader.onerror = (event: Event): void => {
+ reject('contentError');
+ };
+ });
+ }
+ /** Method to handle tar and tar.gz file for shared YAML file content @public */
+ public async targzFile(packageInfo: PACKAGEINFO): Promise<string | ArrayBuffer> {
+ return new Promise<string | ArrayBuffer>((resolve: Function, reject: Function): void => {
+ const httpOptions: GETAPIURLHEADER = this.getHttpOptions();
+ let apiUrl: string = '';
+ apiUrl = packageInfo.packageType === 'nsd' ? environment.NSDESCRIPTORS_URL + '/' + packageInfo.id + '/nsd_content' :
+ environment.VNFPACKAGES_URL + '/' + packageInfo.id + '/package_content';
+ this.restService.getResource(apiUrl, httpOptions).subscribe((response: ArrayBuffer) => {
+ try {
+ // tslint:disable-next-line: no-any
+ const tar: any = new Tar();
+ const originalInput: Uint8Array = pako.inflate(response, { to: 'Uint8Array' });
+ untar(originalInput.buffer).then((extractedFiles: TARSETTINGS[]) => {
+ const getFoldersFiles: {}[] = extractedFiles;
+ const folderNameStr: string = extractedFiles[0].name;
+ getFoldersFiles.forEach((value: TARSETTINGS) => {
+ const getRootFolder: string[] = value.name.split('/');
+ if (value.name.startsWith(folderNameStr) &&
+ (value.name.endsWith('.yaml') || value.name.endsWith('.yml')) &&
+ getRootFolder.length === this.directoryCount) {
+ tar.append(value.name, packageInfo.descriptor, { type: value.type });
+ } else {
+ if (value.type !== 'L') {
+ tar.append(value.name, new Uint8Array(value.buffer), { type: value.type });
+ }
+ }
+ });
+ const out: Uint8Array = tar.out;
+ const originalOutput: Uint8Array = pako.gzip(out);
+ resolve(originalOutput.buffer);
+ }, (err: string) => {
+ reject('');
+ });
+ } catch (e) {
+ reject('');
+ }
+ }, (error: HttpErrorResponse) => {
+ if (error.status === HttpStatus.NOT_FOUND || error.status === HttpStatus.UNAUTHORIZED) {
+ this.router.navigateByUrl('404', { skipLocationChange: true }).catch();
+ } else {
+ this.restService.handleError(error, 'get');
+ reject('');
+ }
+ });
+ });
+ }
+ /** Method to check given string is JSON or not @public */
+ public checkJson(jsonString: string): boolean {
+ jsonString = jsonString.replace(/'/g, '"');
+ try {
+ JSON.parse(jsonString);
+ } catch (e) {
+ return false;
+ }
+ return true;
+ }
+ /** Clean the form before submit @public */
+ public cleanForm(formGroup: FormGroup): void {
+ Object.keys(formGroup.controls).forEach((key: string) => {
+ if ((!isNullOrUndefined((formGroup.get(key) as FormArray | FormGroup).controls)) && key !== 'vimconfig') {
+ // tslint:disable-next-line: no-shadowed-variable
+ for (const { item, index } of (formGroup.get(key).value).map((item: {}, index: number) => ({ item, index }))) {
+ const newFormGroup: FormGroup = (formGroup.get(key) as FormArray).controls[index] as FormGroup;
+ this.cleanForm(newFormGroup);
+ }
+ } else if (formGroup.get(key).value !== undefined && formGroup.get(key).value !== null && key !== 'vimconfig') {
+ if (!Array.isArray(formGroup.get(key).value)) {
+ if (typeof formGroup.get(key).value === 'string') {
+ formGroup.get(key).setValue(formGroup.get(key).value.trim());
+ }
+ }
+ } else if (key === 'vimconfig') {
+ const newFormGroup: FormGroup = formGroup.get(key) as FormGroup;
+ this.cleanForm(newFormGroup);
+ }
+ });
+ }
+ /** Method to return the config of pager value for ngSmarttable @public */
+ public paginationPagerConfig(): PAGERSMARTTABLE {
+ return {
+ display: true,
+ perPage: environment.paginationNumber
+ };
+ }
+ /** Method to return the class for the table for ngSmarttable @public */
+ public tableClassConfig(): SMARTTABLECLASS {
+ return {
+ class: 'table list-data'
+ };
+ }
+ /** Method to return all languages name and its code @public */
+ public languageCodeList(): {}[] {
+ return [
+ { code: 'en', language: 'English' },
+ { code: 'es', language: 'Spanish' },
+ { code: 'pt', language: 'Portuguese' },
+ { code: 'de', language: 'German' }
+ ];
+ }
+ /** Fetch OSM Version @public */
+ public fetchOSMVersion(): void {
+ this.restService.getResource(environment.OSM_VERSION_URL).subscribe((res: { version: string }) => {
+ const version: string[] = res.version.split('+');
+ if (!isNullOrUndefined(version[0])) {
+ this.osmVersion = version[0];
+ } else {
+ this.osmVersion = null;
+ }
+ }, (error: ERRORDATA) => {
+ this.osmVersion = null;
+ this.restService.handleError(error, 'get');
+ });
+ }
+ /** Method to validate file extension and size @private */
+ private vaildataFileInfo(fileInfo: File, fileType: string): boolean {
+ const extension: string = fileInfo.name.substring(fileInfo.name.lastIndexOf('.') + 1);
+ const packageSize: number = CONSTANTNUMBER.oneMB * environment.packageSize;
+ if (extension.toLowerCase() === fileType && fileInfo.size <= packageSize) {
+ return true;
+ }
+ return false;
+ }
+ /** Method to read file content based on type @private */
+ private readFileContent(reader: FileReader, fileInfo: File, fileType: string): void {
+ if (fileType === 'gz') {
+ reader.readAsArrayBuffer(fileInfo);
+ } else {
+ reader.readAsText(fileInfo);
+ }
+ }
+ /** Method to handle http options @public */
+ private getHttpOptions(): GETAPIURLHEADER {
+ return {
+ headers: new HttpHeaders({
+ Accept: 'application/gzip, application/json',
+ 'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0'
+ }),
+ responseType: 'arraybuffer'
+ };
+ }
+}