| kumaran.m | 3b4814a | 2020-05-01 19:48:54 +0530 | [diff] [blame] | 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 | |
| Barath Kumar R | 208bef2 | 2020-07-07 12:28:04 +0530 | [diff] [blame^] | 91 | /** Random color string generator length @private */ |
| 92 | private colorStringLength: number = 256; |
| 93 | |
| kumaran.m | 3b4814a | 2020-05-01 19:48:54 +0530 | [diff] [blame] | 94 | /** Check for the root directory @private */ |
| 95 | private directoryCount: number = 2; |
| 96 | |
| 97 | constructor(restService: RestService, router: Router) { |
| 98 | this.restService = restService; |
| 99 | this.router = router; |
| 100 | } |
| 101 | |
| 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); |
| 115 | } |
| 116 | |
| 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'); |
| 124 | } else { |
| 125 | downloadLink.setAttribute('download', 'OSM_Export_' + shortName + '.tar.gz'); |
| 126 | document.body.appendChild(downloadLink); |
| 127 | downloadLink.click(); |
| 128 | } |
| 129 | } |
| 130 | } |
| 131 | |
| 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(); |
| 135 | } |
| 136 | |
| 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)]; |
| 144 | } |
| 145 | return result; |
| 146 | } |
| 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); |
| 153 | } else { |
| 154 | reject('typeError'); |
| 155 | } |
| 156 | reader.onload = (): void => { |
| 157 | if (reader.result === null) { |
| 158 | reject('contentError'); |
| 159 | } |
| 160 | resolve(reader.result); |
| 161 | }; |
| 162 | reader.onerror = (event: Event): void => { |
| 163 | reject('contentError'); |
| 164 | }; |
| 165 | }); |
| 166 | } |
| 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) => { |
| 175 | try { |
| 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 }); |
| 188 | } else { |
| 189 | if (value.type !== 'L') { |
| 190 | tar.append(value.name, new Uint8Array(value.buffer), { type: value.type }); |
| 191 | } |
| 192 | } |
| 193 | }); |
| 194 | const out: Uint8Array = tar.out; |
| 195 | const originalOutput: Uint8Array = pako.gzip(out); |
| 196 | resolve(originalOutput.buffer); |
| 197 | }, (err: string) => { |
| 198 | reject(''); |
| 199 | }); |
| 200 | } catch (e) { |
| 201 | reject(''); |
| 202 | } |
| 203 | }, (error: HttpErrorResponse) => { |
| 204 | if (error.status === HttpStatus.NOT_FOUND || error.status === HttpStatus.UNAUTHORIZED) { |
| 205 | this.router.navigateByUrl('404', { skipLocationChange: true }).catch(); |
| 206 | } else { |
| 207 | this.restService.handleError(error, 'get'); |
| 208 | reject(''); |
| 209 | } |
| 210 | }); |
| 211 | }); |
| 212 | } |
| 213 | /** Method to check given string is JSON or not @public */ |
| 214 | public checkJson(jsonString: string): boolean { |
| 215 | jsonString = jsonString.replace(/'/g, '"'); |
| 216 | try { |
| 217 | JSON.parse(jsonString); |
| 218 | } catch (e) { |
| 219 | return false; |
| 220 | } |
| 221 | return true; |
| 222 | } |
| 223 | /** Clean the form before submit @public */ |
| 224 | public cleanForm(formGroup: FormGroup): void { |
| 225 | Object.keys(formGroup.controls).forEach((key: string) => { |
| 226 | if ((!isNullOrUndefined((formGroup.get(key) as FormArray | FormGroup).controls)) && key !== 'vimconfig') { |
| 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); |
| 231 | } |
| 232 | } else if (formGroup.get(key).value !== undefined && formGroup.get(key).value !== null && key !== 'vimconfig') { |
| 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()); |
| 236 | } |
| 237 | } |
| 238 | } else if (key === 'vimconfig') { |
| 239 | const newFormGroup: FormGroup = formGroup.get(key) as FormGroup; |
| 240 | this.cleanForm(newFormGroup); |
| 241 | } |
| 242 | }); |
| 243 | } |
| 244 | /** Method to return the config of pager value for ngSmarttable @public */ |
| 245 | public paginationPagerConfig(): PAGERSMARTTABLE { |
| 246 | return { |
| 247 | display: true, |
| 248 | perPage: environment.paginationNumber |
| 249 | }; |
| 250 | } |
| 251 | /** Method to return the class for the table for ngSmarttable @public */ |
| 252 | public tableClassConfig(): SMARTTABLECLASS { |
| 253 | return { |
| 254 | class: 'table list-data' |
| 255 | }; |
| 256 | } |
| 257 | /** Method to return all languages name and its code @public */ |
| 258 | public languageCodeList(): {}[] { |
| 259 | return [ |
| 260 | { code: 'en', language: 'English' }, |
| 261 | { code: 'es', language: 'Spanish' }, |
| 262 | { code: 'pt', language: 'Portuguese' }, |
| 263 | { code: 'de', language: 'German' } |
| 264 | ]; |
| 265 | } |
| 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]; |
| 272 | } else { |
| 273 | this.osmVersion = null; |
| 274 | } |
| 275 | }, (error: ERRORDATA) => { |
| 276 | this.osmVersion = null; |
| 277 | this.restService.handleError(error, 'get'); |
| 278 | }); |
| 279 | } |
| Barath Kumar R | 208bef2 | 2020-07-07 12:28:04 +0530 | [diff] [blame^] | 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 + ')'; |
| 286 | } |
| kumaran.m | 3b4814a | 2020-05-01 19:48:54 +0530 | [diff] [blame] | 287 | /** Method to validate file extension and size @private */ |
| 288 | private vaildataFileInfo(fileInfo: File, fileType: string): boolean { |
| 289 | const extension: string = fileInfo.name.substring(fileInfo.name.lastIndexOf('.') + 1); |
| 290 | const packageSize: number = CONSTANTNUMBER.oneMB * environment.packageSize; |
| 291 | if (extension.toLowerCase() === fileType && fileInfo.size <= packageSize) { |
| 292 | return true; |
| 293 | } |
| 294 | return false; |
| 295 | } |
| 296 | /** Method to read file content based on type @private */ |
| 297 | private readFileContent(reader: FileReader, fileInfo: File, fileType: string): void { |
| 298 | if (fileType === 'gz') { |
| 299 | reader.readAsArrayBuffer(fileInfo); |
| 300 | } else { |
| 301 | reader.readAsText(fileInfo); |
| 302 | } |
| 303 | } |
| 304 | /** Method to handle http options @public */ |
| 305 | private getHttpOptions(): GETAPIURLHEADER { |
| 306 | return { |
| 307 | headers: new HttpHeaders({ |
| 308 | Accept: 'application/gzip, application/json', |
| 309 | 'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0' |
| 310 | }), |
| 311 | responseType: 'arraybuffer' |
| 312 | }; |
| 313 | } |
| 314 | } |