UNPKG

ngx-firebase-cms

Version:

Angular Content Management System using Google Firebase (Authentication, Storage & Firestore)

368 lines 34.3 kB
/** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ import { Component, ElementRef, ViewChild, HostListener } from '@angular/core'; import { UnsubscriptionService } from '../../service/unsubscription.service'; import { FormBuilder, FormControl, Validators } from '@angular/forms'; import { AngularFireAuth } from '@angular/fire/auth'; import { NzMessageService, NzNotificationService } from 'ng-zorro-antd'; import { AngularFireStorage } from '@angular/fire/storage'; import { AuthService } from '../../service/auth.service'; import { HelperService } from '../../service/helper.service'; import * as firebase from 'firebase/app'; import { of } from 'rxjs'; import { AngularFirestore } from '@angular/fire/firestore'; var ProfileComponent = /** @class */ (function () { function ProfileComponent(unsubscription, afAuth, afs, message, storage, auth, fb, notification, helper) { var _this = this; this.unsubscription = unsubscription; this.afAuth = afAuth; this.afs = afs; this.message = message; this.storage = storage; this.auth = auth; this.fb = fb; this.notification = notification; this.helper = helper; this.titlebar = { title: "Profile", description: "Edit your profile", breadcrumbs: [ { title: "Profile", icon: 'team' } ] }; this.showChangePassword = false; this.isLoading = false; this.showDisplayName = false; this.profileURL = null; this.beforeUpload = (/** * @param {?} file * @return {?} */ function (file) { if (file['type'] != "image/jpeg") { _this.message.error("File type should be JPEG"); return false; } else if (file['size'] / 1024 / 1024 > 1) { _this.message.error("File size should be less than 1 Mb"); return false; } else { return true; } }); this.uploadProfilePic = (/** * @param {?} item * @return {?} */ function (item) { _this.message.success("File is uploading"); /** @type {?} */ var timestamp = new Date().valueOf(); /** @type {?} */ var filePath = "/profile/" + timestamp + ".jpeg"; /** @type {?} */ var file = item['file']; /** @type {?} */ var task = _this.storage.upload(filePath, file) .then((/** * @param {?} res * @return {?} */ function (res) { return _this.storage.ref(filePath).getDownloadURL().toPromise(); })) .then((/** * @param {?} res * @return {?} */ function (res) { return _this.afs.collection("users").doc(_this.auth.uid).update({ "profileURL": res, "uploadTime": firebase.firestore.FieldValue.serverTimestamp() }); })) .then((/** * @param {?} res * @return {?} */ function (res) { _this.auth.log("changed profile pic " + timestamp + ".jpeg"); _this.message.success("File Uploaded"); })).catch((/** * @param {?} err * @return {?} */ function (err) { _this.message.error(err); })); return of().subscribe((/** * @param {?} event * @return {?} */ function (event) { if (event['percent'] != 100) { item.onProgress(event, item.file); } else { item.onSuccess(event['body'], item.file, event); } }), (/** * @param {?} err * @return {?} */ function (err) { item.onError(err, item.file); })); }); } /** * @return {?} */ ProfileComponent.prototype.ngOnInit = /** * @return {?} */ function () { var _this = this; this.sub = this.auth.user$.subscribe((/** * @param {?} res * @return {?} */ function (res) { _this.profileURL = res.profileURL; }), (/** * @param {?} err * @return {?} */ function (err) { })); this.initForm(); }; /** * @return {?} */ ProfileComponent.prototype.ngOnDestroy = /** * @return {?} */ function () { this.sub.unsubscribe(); }; /** * @return {?} */ ProfileComponent.prototype.initForm = /** * @return {?} */ function () { this.passwordForm = this.fb.group({ "previousPassword": new FormControl({ value: "", disabled: false }, [Validators.required]), "newPassword": new FormControl({ value: "", disabled: false }, [Validators.required]), }); this.displayNameForm = this.fb.group({ "displayName": new FormControl({ "value": this.auth.displayName, disabled: false }, [Validators.required]) }); }; /** * @return {?} */ ProfileComponent.prototype.changePassword = /** * @return {?} */ function () { var _this = this; if (typeof this.passwordForm.value["newPassword"] == "string") this.passwordForm.controls["newPassword"].setValue(this.passwordForm.value["newPassword"].trim()); if (this.passwordForm.valid && !this.isLoading) { this.isLoading = true; this.afAuth.auth.signInWithEmailAndPassword(this.auth.email, this.passwordForm.value['previousPassword']).then((/** * @param {?} res * @return {?} */ function (res) { /** @type {?} */ var user = _this.afAuth.auth.currentUser; return user.updatePassword(_this.passwordForm.value["newPassword"]); })) .then((/** * @param {?} res * @return {?} */ function (res) { _this.auth.log(" updated the password"); _this.message.success("Change the password"); _this.showChangePassword = !_this.showChangePassword; })) .catch((/** * @param {?} err * @return {?} */ function (err) { _this.message.error(err); })); } else { this.passwordForm.controls["newPassword"].markAsDirty(); } }; /** * @return {?} */ ProfileComponent.prototype.changeDisplayName = /** * @return {?} */ function () { var _this = this; if (typeof this.displayNameForm.value["displayName"] == "string") this.displayNameForm.controls["displayName"].setValue(this.displayNameForm.value["displayName"].trim()); if (this.displayNameForm.valid && !this.isLoading) { this.isLoading = true; this.afs.collection("users").doc(this.auth.uid).update({ "displayName": this.displayNameForm.value["displayName"], "uploadTime": firebase.firestore.FieldValue.serverTimestamp() }).then((/** * @param {?} res * @return {?} */ function (res) { _this.isLoading = false; _this.showDisplayName = !_this.showDisplayName; })); } else { this.displayNameForm.controls["displayName"].markAsDirty(); } }; /** * @return {?} */ ProfileComponent.prototype.getProfilePic = /** * @return {?} */ function () { return (this.profileURL) ? { 'background-image': 'url(\'' + this.profileURL + '\')' } : {}; }; /** * @param {?} e * @return {?} */ ProfileComponent.prototype.keyboardEvent = /** * @param {?} e * @return {?} */ function (e) { if (this.showChangePassword && e.key == 'Escape') { this.notification.blank("ESC", "Escape modal"); this.showChangePassword = false; } if (this.showDisplayName && e.key == 'Escape') { this.notification.blank("ESC", "Escape modal"); this.showDisplayName = false; } if (this.showChangePassword) { if (e.ctrlKey && e.key == 'Enter') { this.notification.blank("⌃ ENTER", "Form Submission"); this.changePassword(); } } if (this.showDisplayName && e.ctrlKey && e.key == 'Enter') { this.notification.blank("⌃ ENTER", "Form Submission"); this.changeDisplayName(); } }; ProfileComponent.decorators = [ { type: Component, args: [{ selector: 'aq-profile', template: "<aq-title-bar [data]=\"titlebar\"></aq-title-bar>\n\n<div class=\"container\">\n <h3>{{ (auth.user$ | async)?.displayName }}</h3>\n <p>Email: {{ (auth.user$ | async)?.email }}</p>\n <p>Roles: {{ (auth.user$ | async)?.roles }}</p>\n <p>Created on: {{ (auth.user$ | async)?.createdTime.toDate() | date: 'medium' }}</p>\n <p>Last login: {{ auth.lastLogin | date: 'medium' }}</p>\n\n <button class=\"m-r-10\" nz-tooltip nzTitle=\"Change Password\" nz-button (click)=\"showChangePassword=true\">\n <i nz-icon type=\"security-scan\" theme=\"outline\"></i> Password\n </button>\n\n <button class=\"m-r-10\" nz-tooltip nzTitle=\"Change Display Name\" nz-button (click)=\"showDisplayName=true\">\n <i nz-icon type=\"font-colors\" theme=\"outline\"></i> Display Name\n </button>\n\n <nz-upload class=\"m-r-10\" [nzBeforeUpload]=\"beforeUpload\" [nzCustomRequest]=\"uploadProfilePic\"\n [nzShowUploadList]=\"false\">\n <button #uploadButton nz-tooltip nzTitle=\"Change Profile Image\" nz-button>\n <i nz-icon type=\"picture\" theme=\"outline\"></i> Profile Image\n </button>\n </nz-upload>\n</div>\n\n<nz-drawer nzWidth=\"100%\" [nzVisible]=\"showChangePassword\" nzTitle=\"Change Password\" (nzOnClose)=\"showChangePassword = !showChangePassword\">\n <form nz-form [formGroup]=\"passwordForm\" (ngSubmit)=\"changePassword()\">\n <nz-form-item>\n <nz-form-control>\n <label>Previous Password</label>\n <input type=\"password\" nz-input formControlName=\"previousPassword\" placeholder=\"Previous Password\"\n autocomplete=\"password\" autofocus>\n <nz-form-explain\n *ngIf=\"passwordForm.get('previousPassword').dirty && passwordForm.get('previousPassword').errors\">\n Please input\n your previous password!</nz-form-explain>\n </nz-form-control>\n </nz-form-item>\n <nz-form-item>\n <nz-form-control>\n <label>New Password</label>\n <input type=\"password\" nz-input formControlName=\"newPassword\" placeholder=\"New Password\" autocomplete=\"password\" autofocus>\n <nz-form-explain\n *ngIf=\"passwordForm.get('newPassword').dirty && passwordForm.get('newPassword').errors\">Please input\n your new\n password!</nz-form-explain>\n </nz-form-control>\n </nz-form-item>\n </form>\n <div class=\"footer\">\n <button type=\"button\" (click)=\"changePassword()\" class=\"ant-btn ant-btn-primary\">Submit </button>\n <button type=\"button\" (click)=\"showChangePassword = !showChangePassword\" class=\"ant-btn\">Cancel </button>\n </div>\n</nz-drawer>\n\n<nz-drawer nzWidth=\"100%\" [nzVisible]=\"showDisplayName\" nzTitle=\"Change Display Name\" (nzOnClose)=\"showDisplayName = !showDisplayName\">\n <form nz-form [formGroup]=\"displayNameForm\" (ngSubmit)=\"changeDisplayName()\">\n <nz-form-item>\n <nz-form-control>\n <label>Your Display Name</label>\n <input type=\"text\" nz-input formControlName=\"displayName\" placeholder=\"Please enter your display name\"\n autocomplete=\"displayName\" autofocus>\n <nz-form-explain\n *ngIf=\"displayNameForm.get('displayName').dirty && displayNameForm.get('displayName').errors\">Please\n input\n your Display Name!</nz-form-explain>\n </nz-form-control>\n </nz-form-item>\n </form>\n <div class=\"footer\">\n <button type=\"button\" (click)=\"changeDisplayName()\" class=\"ant-btn ant-btn-primary\">Submit </button>\n <button type=\"button\" (click)=\"showDisplayName = !showDisplayName\" class=\"ant-btn\">Cancel </button>\n </div>\n</nz-drawer>\n", styles: [".img-rounded{border-radius:50%;width:80%;position:relative}.img-rounded:hover{opacity:1}.footer{position:absolute;bottom:0;width:100%;border-top:1px solid #e8e8e8;padding:10px 16px;left:0;z-index:9999;background:#fff}.footer button{margin-left:10px}.m-r-10{margin-right:10px}.w-200{width:200px}.user-profile{width:200px;height:200px;background:0 0/cover #efefef;border-radius:50%}"] }] } ]; /** @nocollapse */ ProfileComponent.ctorParameters = function () { return [ { type: UnsubscriptionService }, { type: AngularFireAuth }, { type: AngularFirestore }, { type: NzMessageService }, { type: AngularFireStorage }, { type: AuthService }, { type: FormBuilder }, { type: NzNotificationService }, { type: HelperService } ]; }; ProfileComponent.propDecorators = { uploadButton: [{ type: ViewChild, args: ['uploadButton',] }], keyboardEvent: [{ type: HostListener, args: ['document:keydown', ['$event'],] }] }; return ProfileComponent; }()); export { ProfileComponent }; if (false) { /** @type {?} */ ProfileComponent.prototype.uploadButton; /** @type {?} */ ProfileComponent.prototype.titlebar; /** @type {?} */ ProfileComponent.prototype.showChangePassword; /** @type {?} */ ProfileComponent.prototype.passwordForm; /** @type {?} */ ProfileComponent.prototype.displayNameForm; /** @type {?} */ ProfileComponent.prototype.isLoading; /** @type {?} */ ProfileComponent.prototype.showDisplayName; /** @type {?} */ ProfileComponent.prototype.profileURL; /** @type {?} */ ProfileComponent.prototype.sub; /** @type {?} */ ProfileComponent.prototype.beforeUpload; /** @type {?} */ ProfileComponent.prototype.uploadProfilePic; /** * @type {?} * @private */ ProfileComponent.prototype.unsubscription; /** * @type {?} * @private */ ProfileComponent.prototype.afAuth; /** * @type {?} * @private */ ProfileComponent.prototype.afs; /** * @type {?} * @private */ ProfileComponent.prototype.message; /** * @type {?} * @private */ ProfileComponent.prototype.storage; /** @type {?} */ ProfileComponent.prototype.auth; /** * @type {?} * @private */ ProfileComponent.prototype.fb; /** * @type {?} * @private */ ProfileComponent.prototype.notification; /** * @type {?} * @private */ ProfileComponent.prototype.helper; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvZmlsZS5jb21wb25lbnQuanMiLCJzb3VyY2VSb290Ijoibmc6Ly9uZ3gtZmlyZWJhc2UtY21zLyIsInNvdXJjZXMiOlsibGliL2NvbXBvbmVudC9wcm9maWxlL3Byb2ZpbGUuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7QUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFVLFVBQVUsRUFBRSxTQUFTLEVBQUUsWUFBWSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBRXZGLE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxNQUFNLHNDQUFzQyxDQUFDO0FBQzdFLE9BQU8sRUFBYSxXQUFXLEVBQUUsV0FBVyxFQUFFLFVBQVUsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ2pGLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUNyRCxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUscUJBQXFCLEVBQTZCLE1BQU0sZUFBZSxDQUFDO0FBQ25HLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQzNELE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUN6RCxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sOEJBQThCLENBQUM7QUFDN0QsT0FBTyxLQUFLLFFBQVEsTUFBTSxjQUFjLENBQUM7QUFFekMsT0FBTyxFQUFFLEVBQUUsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUMxQixPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUczRDtJQTJCRSwwQkFDVSxjQUFxQyxFQUNyQyxNQUF1QixFQUN2QixHQUFxQixFQUNyQixPQUF5QixFQUN6QixPQUEyQixFQUM1QixJQUFpQixFQUNoQixFQUFlLEVBQ2YsWUFBbUMsRUFDbkMsTUFBcUI7UUFUL0IsaUJBVUs7UUFUSyxtQkFBYyxHQUFkLGNBQWMsQ0FBdUI7UUFDckMsV0FBTSxHQUFOLE1BQU0sQ0FBaUI7UUFDdkIsUUFBRyxHQUFILEdBQUcs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aXQsIEVsZW1lbnRSZWYsIFZpZXdDaGlsZCwgSG9zdExpc3RlbmVyIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBCcmVhZGNydW1iIH0gZnJvbSAnLi4vLi4vaW50ZXJmYWNlL2JyZWFkY3J1bWInO1xuaW1wb3J0IHsgVW5zdWJzY3JpcHRpb25TZXJ2aWNlIH0gZnJvbSAnLi4vLi4vc2VydmljZS91bnN1YnNjcmlwdGlvbi5zZXJ2aWNlJztcbmltcG9ydCB7IEZvcm1Hcm91cCwgRm9ybUJ1aWxkZXIsIEZvcm1Db250cm9sLCBWYWxpZGF0b3JzIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuaW1wb3J0IHsgQW5ndWxhckZpcmVBdXRoIH0gZnJvbSAnQGFuZ3VsYXIvZmlyZS9hdXRoJztcbmltcG9ydCB7IE56TWVzc2FnZVNlcnZpY2UsIE56Tm90aWZpY2F0aW9uU2VydmljZSwgVXBsb2FkWEhSQXJncywgVXBsb2FkRmlsZSB9IGZyb20gJ25nLXpvcnJvLWFudGQnO1xuaW1wb3J0IHsgQW5ndWxhckZpcmVTdG9yYWdlIH0gZnJvbSAnQGFuZ3VsYXIvZmlyZS9zdG9yYWdlJztcbmltcG9ydCB7IEF1dGhTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vc2VydmljZS9hdXRoLnNlcnZpY2UnO1xuaW1wb3J0IHsgSGVscGVyU2VydmljZSB9IGZyb20gJy4uLy4uL3NlcnZpY2UvaGVscGVyLnNlcnZpY2UnO1xuaW1wb3J0ICogYXMgZmlyZWJhc2UgZnJvbSAnZmlyZWJhc2UvYXBwJztcbmltcG9ydCB7IEh0dHBFdmVudCB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbi9odHRwJztcbmltcG9ydCB7IG9mIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBBbmd1bGFyRmlyZXN0b3JlIH0gZnJvbSAnQGFuZ3VsYXIvZmlyZS9maXJlc3RvcmUnO1xuaW1wb3J0IHsgVGl0bGViYXIgfSBmcm9tICcuLi8uLi9pbnRlcmZhY2UvdGl0bGViYXInO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdhcS1wcm9maWxlJyxcbiAgdGVtcGxhdGVVcmw6ICcuL3Byb2ZpbGUuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybHM6IFsnLi9wcm9maWxlLmNvbXBvbmVudC5jc3MnXVxufSlcbmV4cG9ydCBjbGFzcyBQcm9maWxlQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0IHtcbiAgQFZpZXdDaGlsZCgndXBsb2FkQnV0dG9uJykgdXBsb2FkQnV0dG9uOiBFbGVtZW50UmVmXG5cbiAgdGl0bGViYXI6IFRpdGxlYmFyID0ge1xuICAgIHRpdGxlOiBcIlByb2ZpbGVcIixcbiAgICBkZXNjcmlwdGlvbjogXCJFZGl0IHlvdXIgcHJvZmlsZVwiLFxuICAgIGJyZWFkY3J1bWJzOiBbXG4gICAgICB7XG4gICAgICAgIHRpdGxlOiBcIlByb2ZpbGVcIixcbiAgICAgICAgaWNvbjogJ3RlYW0nXG4gICAgICB9XG4gICAgXVxuICB9XG5cbiAgc2hvd0NoYW5nZVBhc3N3b3JkID0gZmFsc2VcbiAgcGFzc3dvcmRGb3JtOiBGb3JtR3JvdXBcbiAgZGlzcGxheU5hbWVGb3JtOiBGb3JtR3JvdXBcbiAgaXNMb2FkaW5nID0gZmFsc2VcbiAgc2hvd0Rpc3BsYXlOYW1lID0gZmFsc2VcbiAgcHJvZmlsZVVSTCA9IG51bGxcbiAgc3ViXG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSB1bnN1YnNjcmlwdGlvbjogVW5zdWJzY3JpcHRpb25TZXJ2aWNlLFxuICAgIHByaXZhdGUgYWZBdXRoOiBBbmd1bGFyRmlyZUF1dGgsXG4gICAgcHJpdmF0ZSBhZnM6IEFuZ3VsYXJGaXJlc3RvcmUsXG4gICAgcHJpdmF0ZSBtZXNzYWdlOiBOek1lc3NhZ2VTZXJ2aWNlLFxuICAgIHByaXZhdGUgc3RvcmFnZTogQW5ndWxhckZpcmVTdG9yYWdlLFxuICAgIHB1YmxpYyBhdXRoOiBBdXRoU2VydmljZSxcbiAgICBwcml2YXRlIGZiOiBGb3JtQnVpbGRlcixcbiAgICBwcml2YXRlIG5vdGlmaWNhdGlvbjogTnpOb3RpZmljYXRpb25TZXJ2aWNlLFxuICAgIHByaXZhdGUgaGVscGVyOiBIZWxwZXJTZXJ2aWNlXG4gICkgeyB9XG5cbiAgbmdPbkluaXQoKSB7XG4gICAgdGhpcy5zdWIgPSB0aGlzLmF1dGgudXNlciQuc3Vic2NyaWJlKHJlcyA9PiB7XG4gICAgICB0aGlzLnByb2ZpbGVVUkwgPSByZXMucHJvZmlsZVVSTFxuICAgIH0sIGVyciA9PiB7fSlcbiAgICB0aGlzLmluaXRGb3JtKClcbiAgfVxuXG4gIG5nT25EZXN0cm95KCkge1xuICAgIHRoaXMuc3ViLnVuc3Vic2NyaWJlKClcbiAgfVxuXG4gIGluaXRGb3JtKCkge1xuICAgIHRoaXMucGFzc3dvcmRGb3JtID0gdGhpcy5mYi5ncm91cCh7XG4gICAgICBcInByZXZpb3VzUGFzc3dvcmRcIjogbmV3IEZvcm1Db250cm9sKHsgdmFsdWU6IFwiXCIsIGRpc2FibGVkOiBmYWxzZSB9LCBbVmFsaWRhdG9ycy5yZXF1aXJlZF0pLFxuICAgICAgXCJuZXdQYXNzd29yZFwiOiBuZXcgRm9ybUNvbnRyb2woeyB2YWx1ZTogXCJcIiwgZGlzYWJsZWQ6IGZhbHNlIH0sIFtWYWxpZGF0b3JzLnJlcXVpcmVkXSksXG4gICAgfSlcbiAgICB0aGlzLmRpc3BsYXlOYW1lRm9ybSA9IHRoaXMuZmIuZ3JvdXAoe1xuICAgICAgXCJkaXNwbGF5TmFtZVwiOiBuZXcgRm9ybUNvbnRyb2woeyBcInZhbHVlXCI6IHRoaXMuYXV0aC5kaXNwbGF5TmFtZSwgZGlzYWJsZWQ6IGZhbHNlIH0sIFtWYWxpZGF0b3JzLnJlcXVpcmVkXSlcbiAgICB9KVxuICB9XG5cbiAgY2hhbmdlUGFzc3dvcmQoKSB7XG4gICAgaWYgKHR5cGVvZiB0aGlzLnBhc3N3b3JkRm9ybS52YWx1ZVtcIm5ld1Bhc3N3b3JkXCJdID09IFwic3RyaW5nXCIpIHRoaXMucGFzc3dvcmRGb3JtLmNvbnRyb2xzW1wibmV3UGFzc3dvcmRcIl0uc2V0VmFsdWUodGhpcy5wYXNzd29yZEZvcm0udmFsdWVbXCJuZXdQYXNzd29yZFwiXS50cmltKCkpXG4gICAgaWYgKHRoaXMucGFzc3dvcmRGb3JtLnZhbGlkICYmICF0aGlzLmlzTG9hZGluZykge1xuICAgICAgdGhpcy5pc0xvYWRpbmcgPSB0cnVlXG4gICAgICB0aGlzLmFmQXV0aC5hdXRoLnNpZ25JbldpdGhFbWFpbEFuZFBhc3N3b3JkKHRoaXMuYXV0aC5lbWFpbCwgdGhpcy5wYXNzd29yZEZvcm0udmFsdWVbJ3ByZXZpb3VzUGFzc3dvcmQnXSkudGhlbihyZXMgPT4ge1xuICAgICAgICBsZXQgdXNlciA9IHRoaXMuYWZBdXRoLmF1dGguY3VycmVudFVzZXJcbiAgICAgICAgcmV0dXJuIHVzZXIudXBkYXRlUGFzc3dvcmQodGhpcy5wYXNzd29yZEZvcm0udmFsdWVbXCJuZXdQYXNzd29yZFwiXSlcbiAgICAgIH0pXG4gICAgICAgIC50aGVuKHJlcyA9PiB7XG4gICAgICAgICAgdGhpcy5hdXRoLmxvZyhgIHVwZGF0ZWQgdGhlIHBhc3N3b3JkYClcbiAgICAgICAgICB0aGlzLm1lc3NhZ2Uuc3VjY2VzcyhgQ2hhbmdlIHRoZSBwYXNzd29yZGApXG4gICAgICAgICAgdGhpcy5zaG93Q2hhbmdlUGFzc3dvcmQgPSAhdGhpcy5zaG93Q2hhbmdlUGFzc3dvcmRcbiAgICAgICAgfSlcbiAgICAgICAgLmNhdGNoKGVyciA9PiB7XG4gICAgICAgICAgdGhpcy5tZXNzYWdlLmVycm9yKGVycilcbiAgICAgICAgfSlcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5wYXNzd29yZEZvcm0uY29udHJvbHNbXCJuZXdQYXNzd29yZFwiXS5tYXJrQXNEaXJ0eSgpXG4gICAgfVxuICB9XG5cbiAgY2hhbmdlRGlzcGxheU5hbWUoKSB7XG4gICAgaWYgKHR5cGVvZiB0aGlzLmRpc3BsYXlOYW1lRm9ybS52YWx1ZVtcImRpc3BsYXlOYW1lXCJdID09IFwic3RyaW5nXCIpIHRoaXMuZGlzcGxheU5hbWVGb3JtLmNvbnRyb2xzW1wiZGlzcGxheU5hbWVcIl0uc2V0VmFsdWUodGhpcy5kaXNwbGF5TmFtZUZvcm0udmFsdWVbXCJkaXNwbGF5TmFtZVwiXS50cmltKCkpXG4gICAgaWYgKHRoaXMuZGlzcGxheU5hbWVGb3JtLnZhbGlkICYmICF0aGlzLmlzTG9hZGluZykge1xuICAgICAgdGhpcy5pc0xvYWRpbmcgPSB0cnVlXG4gICAgICB0aGlzLmFmcy5jb2xsZWN0aW9uKFwidXNlcnNcIikuZG9jKHRoaXMuYXV0aC51aWQpLnVwZGF0ZSh7XG4gICAgICAgIFwiZGlzcGxheU5hbWVcIjogdGhpcy5kaXNwbGF5TmFtZUZvcm0udmFsdWVbXCJkaXNwbGF5TmFtZVwiXSxcbiAgICAgICAgXCJ1cGxvYWRUaW1lXCI6IGZpcmViYXNlLmZpcmVzdG9yZS5GaWVsZFZhbHVlLnNlcnZlclRpbWVzdGFtcCgpXG4gICAgICB9KS50aGVuKHJlcyA9PiB7XG4gICAgICAgIHRoaXMuaXNMb2FkaW5nID0gZmFsc2VcbiAgICAgICAgdGhpcy5zaG93RGlzcGxheU5hbWUgPSAhdGhpcy5zaG93RGlzcGxheU5hbWVcbiAgICAgIH0pXG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuZGlzcGxheU5hbWVGb3JtLmNvbnRyb2xzW1wiZGlzcGxheU5hbWVcIl0ubWFya0FzRGlydHkoKVxuICAgIH1cbiAgfVxuXG4gIGJlZm9yZVVwbG9hZCA9IChmaWxlOiBVcGxvYWRGaWxlKTogYm9vbGVhbiA9PiB7XG4gICAgaWYgKGZpbGVbJ3R5cGUnXSAhPSBcImltYWdlL2pwZWdcIikge1xuICAgICAgdGhpcy5tZXNzYWdlLmVycm9yKFwiRmlsZSB0eXBlIHNob3VsZCBiZSBKUEVHXCIpXG4gICAgICByZXR1cm4gZmFsc2VcbiAgICB9IGVsc2UgaWYgKGZpbGVbJ3NpemUnXSAvIDEwMjQgLyAxMDI0ID4gMSkge1xuICAgICAgdGhpcy5tZXNzYWdlLmVycm9yKFwiRmlsZSBzaXplIHNob3VsZCBiZSBsZXNzIHRoYW4gMSBNYlwiKVxuICAgICAgcmV0dXJuIGZhbHNlXG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiB0cnVlXG4gICAgfVxuICB9XG5cbiAgdXBsb2FkUHJvZmlsZVBpYyA9IChpdGVtOiBVcGxvYWRYSFJBcmdzKSA9PiB7XG4gICAgdGhpcy5tZXNzYWdlLnN1Y2Nlc3MoYEZpbGUgaXMgdXBsb2FkaW5nYClcbiAgICBsZXQgdGltZXN0YW1wID0gbmV3IERhdGUoKS52YWx1ZU9mKClcbiAgICBsZXQgZmlsZVBhdGggPSBgL3Byb2ZpbGUvJHt0aW1lc3RhbXB9LmpwZWdgXG4gICAgbGV0IGZpbGUgPSBpdGVtWydmaWxlJ11cbiAgICBjb25zdCB0YXNrID0gdGhpcy5zdG9yYWdlLnVwbG9hZChmaWxlUGF0aCwgZmlsZSlcbiAgICAgIC50aGVuKHJlcyA9PiB7XG4gICAgICAgIHJldHVybiB0aGlzLnN0b3JhZ2UucmVmKGZpbGVQYXRoKS5nZXREb3dubG9hZFVSTCgpLnRvUHJvbWlzZSgpXG4gICAgICB9KVxuICAgICAgLnRoZW4ocmVzID0+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYWZzLmNvbGxlY3Rpb24oXCJ1c2Vyc1wiKS5kb2ModGhpcy5hdXRoLnVpZCkudXBkYXRlKHtcbiAgICAgICAgICBcInByb2ZpbGVVUkxcIjogcmVzLFxuICAgICAgICAgIFwidXBsb2FkVGltZVwiOiBmaXJlYmFzZS5maXJlc3RvcmUuRmllbGRWYWx1ZS5zZXJ2ZXJUaW1lc3RhbXAoKVxuICAgICAgICB9KVxuICAgICAgfSlcbiAgICAgIC50aGVuKHJlcyA9PiB7XG4gICAgICAgIHRoaXMuYXV0aC5sb2coYGNoYW5nZWQgcHJvZmlsZSBwaWMgJHt0aW1lc3RhbXB9LmpwZWdgKVxuICAgICAgICB0aGlzLm1lc3NhZ2Uuc3VjY2VzcyhcIkZpbGUgVXBsb2FkZWRcIilcbiAgICAgIH0pLmNhdGNoKGVyciA9PiB7XG4gICAgICAgIHRoaXMubWVzc2FnZS5lcnJvcihlcnIpXG4gICAgICB9KVxuICAgIHJldHVybiBvZigpLnN1YnNjcmliZSgoZXZlbnQ6IEh0dHBFdmVudDx7fT4pID0+IHtcbiAgICAgIGlmIChldmVudFsncGVyY2VudCddICE9IDEwMCkge1xuICAgICAgICBpdGVtLm9uUHJvZ3Jlc3MoZXZlbnQsIGl0ZW0uZmlsZSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpdGVtLm9uU3VjY2VzcyhldmVudFsnYm9keSddLCBpdGVtLmZpbGUsIGV2ZW50KTtcbiAgICAgIH1cbiAgICB9LCAoZXJyKSA9PiB7XG4gICAgICBpdGVtLm9uRXJyb3IoZXJyLCBpdGVtLmZpbGUpO1xuICAgIH0pXG4gIH1cblxuICBnZXRQcm9maWxlUGljKCkge1xuICAgIHJldHVybiAodGhpcy5wcm9maWxlVVJMKSA/IHsgJ2JhY2tncm91bmQtaW1hZ2UnOiAndXJsKFxcJycgKyB0aGlzLnByb2ZpbGVVUkwgKyAnXFwnKScgfSA6IHt9XG4gIH1cblxuICBASG9zdExpc3RlbmVyKCdkb2N1bWVudDprZXlkb3duJywgWyckZXZlbnQnXSlcbiAga2V5Ym9hcmRFdmVudChlOiBLZXlib2FyZEV2ZW50KSB7XG4gICAgaWYgKHRoaXMuc2hvd0NoYW5nZVBhc3N3b3JkICYmIGUua2V5ID09ICdFc2NhcGUnKSB7XG4gICAgICB0aGlzLm5vdGlmaWNhdGlvbi5ibGFuayhcIkVTQ1wiLCBcIkVzY2FwZSBtb2RhbFwiKVxuICAgICAgdGhpcy5zaG93Q2hhbmdlUGFzc3dvcmQgPSBmYWxzZVxuICAgIH1cblxuICAgIGlmICh0aGlzLnNob3dEaXNwbGF5TmFtZSAmJiBlLmtleSA9PSAnRXNjYXBlJykge1xuICAgICAgdGhpcy5ub3RpZmljYXRpb24uYmxhbmsoXCJFU0NcIiwgXCJFc2NhcGUgbW9kYWxcIilcbiAgICAgIHRoaXMuc2hvd0Rpc3BsYXlOYW1lID0gZmFsc2VcbiAgICB9XG5cbiAgICBpZiAodGhpcy5zaG93Q2hhbmdlUGFzc3dvcmQpIHtcbiAgICAgIGlmIChlLmN0cmxLZXkgJiYgZS5rZXkgPT0gJ0VudGVyJykge1xuICAgICAgICB0aGlzLm5vdGlmaWNhdGlvbi5ibGFuayhcIuKMgyBFTlRFUlwiLCBcIkZvcm0gU3VibWlzc2lvblwiKVxuICAgICAgICB0aGlzLmNoYW5nZVBhc3N3b3JkKClcbiAgICAgIH1cbiAgICB9XG4gICAgXG4gICAgaWYgKHRoaXMuc2hvd0Rpc3BsYXlOYW1lICYmIGUuY3RybEtleSAmJiBlLmtleSA9PSAnRW50ZXInKSB7XG4gICAgICB0aGlzLm5vdGlmaWNhdGlvbi5ibGFuayhcIuKMgyBFTlRFUlwiLCBcIkZvcm0gU3VibWlzc2lvblwiKVxuICAgICAgdGhpcy5jaGFuZ2VEaXNwbGF5TmFtZSgpXG4gICAgfVxuICB9XG59XG4iXX0=