ngx-auth-firebaseui-updated
Version:
From ngx-auth-firbaseui but updated to fix dependency issues with Angular 16. Open Source Library for Angular Web Apps to integrate a material user interface for firebase authentication
290 lines • 38.7 kB
JavaScript
import '@firebase/auth';
import { EventEmitter, forwardRef, Inject, Injectable } from '@angular/core';
import { MAT_SNACK_BAR_DEFAULT_OPTIONS } from '@angular/material/snack-bar';
import firebase from 'firebase/compat/app';
import { BehaviorSubject } from 'rxjs';
import { map, take } from 'rxjs/operators';
import { Accounts } from '../enums';
import { NgxAuthFirebaseUIConfigToken } from '../tokens';
import * as i0 from "@angular/core";
import * as i1 from "@angular/fire/compat/auth";
import * as i2 from "@angular/material/snack-bar";
import * as i3 from "./firestore-sync.service";
export const facebookAuthProvider = new firebase.auth.FacebookAuthProvider();
export const googleAuthProvider = new firebase.auth.GoogleAuthProvider();
export const appleAuthProvider = new firebase.auth.OAuthProvider("apple.com");
export const twitterAuthProvider = new firebase.auth.TwitterAuthProvider();
export const githubAuthProvider = new firebase.auth.GithubAuthProvider();
export const microsoftAuthProvider = new firebase.auth.OAuthProvider("microsoft.com");
export const yahooAuthProvider = new firebase.auth.OAuthProvider("yahoo.com");
export var AuthProvider;
(function (AuthProvider) {
AuthProvider["ALL"] = "all";
AuthProvider["ANONYMOUS"] = "anonymous";
AuthProvider["EmailAndPassword"] = "firebase";
AuthProvider["Google"] = "google";
AuthProvider["Apple"] = "apple";
AuthProvider["Facebook"] = "facebook";
AuthProvider["Twitter"] = "twitter";
AuthProvider["Github"] = "github";
AuthProvider["Microsoft"] = "microsoft";
AuthProvider["Yahoo"] = "yahoo";
AuthProvider["PhoneNumber"] = "phoneNumber";
})(AuthProvider || (AuthProvider = {}));
export class AuthProcessService {
get user$() {
return this._user$.asObservable();
}
constructor(afa, config, snackBar, fireStoreService, matSnackBarConfig) {
this.afa = afa;
this.config = config;
this.snackBar = snackBar;
this.fireStoreService = fireStoreService;
this.matSnackBarConfig = matSnackBarConfig;
this.onSuccessEmitter = new EventEmitter();
this.onErrorEmitter = new EventEmitter();
// Useful to know about auth state even between reloads.
// Replace emailConfirmationSent and emailToConfirm.
this._user$ = new BehaviorSubject(null);
}
listenToUserEvents() {
this.afa.user.subscribe((user) => {
this._user$.next(user);
this.user = user;
});
}
/**
* Reset the password of the ngx-auth-firebaseui-user via email
*
* @param email - the email to reset
*/
async resetPassword(email) {
try {
console.log("Password reset email sent");
return await this.afa.sendPasswordResetEmail(email);
}
catch (error) {
return this.notifyError(error);
}
}
/**
* General sign in mechanism to authenticate the users with a firebase project
* using a traditional way, via username and password or by using an authentication provider
* like google, facebook, twitter and github
*
* @param provider - the provider to authenticate with (google, facebook, twitter, github)
* @param credentials optional email and password
*/
async signInWith(provider, credentials) {
try {
let signInResult;
switch (provider) {
case AuthProvider.ANONYMOUS:
signInResult = (await this.afa.signInAnonymously());
break;
case AuthProvider.EmailAndPassword:
signInResult = (await this.afa.signInWithEmailAndPassword(credentials.email, credentials.password));
break;
case AuthProvider.Google:
signInResult = (await this.afa.signInWithPopup(googleAuthProvider));
break;
case AuthProvider.Apple:
signInResult = (await this.afa.signInWithPopup(appleAuthProvider));
break;
case AuthProvider.Facebook:
signInResult = (await this.afa.signInWithPopup(facebookAuthProvider));
break;
case AuthProvider.Twitter:
signInResult = (await this.afa.signInWithPopup(twitterAuthProvider));
break;
case AuthProvider.Github:
signInResult = (await this.afa.signInWithPopup(githubAuthProvider));
break;
case AuthProvider.Microsoft:
signInResult = (await this.afa.signInWithPopup(microsoftAuthProvider));
break;
case AuthProvider.Yahoo:
signInResult = (await this.afa.signInWithPopup(yahooAuthProvider));
break;
case AuthProvider.PhoneNumber:
// coming soon - see feature/sms branch
break;
default:
throw new Error(`${AuthProvider[provider]} is not available as auth provider`);
}
await this.handleSuccess(signInResult);
}
catch (err) {
this.handleError(err);
}
}
/**
* Sign up new users via email and password.
* After that the ngx-auth-firebaseui-user should verify and confirm an email sent via the firebase
*
* @param displayName - the displayName if the new ngx-auth-firebaseui-user
* @param credentials email and password
* @returns -
*/
async signUp(displayName, credentials) {
try {
const userCredential = await this.afa.createUserWithEmailAndPassword(credentials.email, credentials.password);
const user = userCredential.user;
await this.updateProfile(displayName, user.photoURL);
if (this.config.enableFirestoreSync) {
await this.fireStoreService.getUserDocRefByUID(user.uid).set({
uid: user.uid,
displayName,
email: user.email,
photoURL: user.photoURL,
});
}
if (this.config.enableEmailVerification) {
await user.sendEmailVerification();
}
// Legacy fields
this.emailConfirmationSent = true;
this.emailToConfirm = credentials.email;
await this.handleSuccess(userCredential);
}
catch (err) {
this.handleError(err);
}
}
async sendNewVerificationEmail() {
if (!this.user) {
return Promise.reject(new Error("No signed in user"));
}
return this.user.sendEmailVerification();
}
async signOut() {
try {
await this.afa.signOut();
}
catch (error) {
this.notifyError(error);
}
}
/**
* Update the profile (name + photo url) of the authenticated ngx-auth-firebaseui-user in the
* firebase authentication feature (not in firestore)
*
* @param name - the new name of the authenticated ngx-auth-firebaseui-user
* @param photoURL - the new photo url of the authenticated ngx-auth-firebaseui-user
* @returns -
*/
updateProfile(name, photoURL) {
return this.afa.currentUser.then((user) => {
if (!photoURL) {
return user.updateProfile({ displayName: name });
}
else {
return user.updateProfile({ displayName: name, photoURL });
}
});
}
parseUserInfo(user) {
return {
uid: user.uid,
displayName: user.displayName,
email: user.email,
phoneNumber: user.phoneNumber,
photoURL: user.photoURL,
providerId: user.providerData.length > 0 ? user.providerData[0].providerId : null,
};
}
getUserPhotoUrl() {
return this._user$.pipe(map((user) => {
if (!user) {
return null;
}
else if (user.photoURL) {
return user.photoURL;
}
else if (user.emailVerified) {
return this.getPhotoPath(Accounts.CHECK);
}
else if (user.isAnonymous) {
return this.getPhotoPath(Accounts.OFF);
}
else {
return this.getPhotoPath(Accounts.NONE);
}
}));
}
getPhotoPath(image) {
return `assets/user/${image}.svg`;
}
signInWithPhoneNumber() {
// todo: 3.1.18
}
async handleSuccess(userCredential) {
if (this.config.useRawUserCredential) {
this.onSuccessEmitter.next(userCredential);
}
else {
this.onSuccessEmitter.next(userCredential.user);
}
if (this.config.enableFirestoreSync) {
try {
await this.fireStoreService.updateUserData(this.parseUserInfo(userCredential.user));
}
catch (e) {
console.error(`Error occurred while updating user data with firestore: ${e}`);
}
}
if (this.config.toastMessageOnAuthSuccess) {
const fallbackMessage = `Hello ${userCredential.user.displayName ? userCredential.user.displayName : ""}!`;
this.showToast(this.messageOnAuthSuccess || fallbackMessage);
}
}
handleError(error) {
this.notifyError(error);
console.error(error);
}
// Refresh user info. Can be useful for instance to get latest status regarding email verification.
reloadUserInfo() {
return this._user$
.pipe(take(1))
.subscribe((user) => user && user.reload());
}
// Search for an error message.
// Consumers of this library are given the possibility to provide a
// function in case they want to instrument message based on error properties.
getMessageOnAuthError(error) {
// eslint-disable-next-line no-bitwise
return (error.toString() || "Sorry, something went wrong. Please retry later.");
}
// Show a toast using current snackbar config. If message is empty, no toast is displayed allowing to opt-out when needed.
// Default MatSnackBarConfig has no duration, meaning it stays visible forever.
// If that's the case, an action button is added to allow the end-user to dismiss the toast.
showToast(message) {
if (message) {
this.snackBar.open(message, this.matSnackBarConfig.duration ? null : "OK");
}
}
showErrorToast(error) {
if (this.config.toastMessageOnAuthError) {
this.showToast(this.getMessageOnAuthError(error));
}
}
notifyError(error) {
this.onErrorEmitter.emit(error);
this.showErrorToast(error);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AuthProcessService, deps: [{ token: i1.AngularFireAuth }, { token: forwardRef(() => NgxAuthFirebaseUIConfigToken) }, { token: i2.MatSnackBar }, { token: i3.FirestoreSyncService }, { token: MAT_SNACK_BAR_DEFAULT_OPTIONS }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AuthProcessService, providedIn: "root" }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AuthProcessService, decorators: [{
type: Injectable,
args: [{
providedIn: "root",
}]
}], ctorParameters: function () { return [{ type: i1.AngularFireAuth }, { type: undefined, decorators: [{
type: Inject,
args: [forwardRef(() => NgxAuthFirebaseUIConfigToken)]
}] }, { type: i2.MatSnackBar }, { type: i3.FirestoreSyncService }, { type: i2.MatSnackBarConfig, decorators: [{
type: Inject,
args: [MAT_SNACK_BAR_DEFAULT_OPTIONS]
}] }]; } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXV0aC1wcm9jZXNzLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtYXV0aC1maXJlYmFzZXVpL3NyYy9saWIvc2VydmljZXMvYXV0aC1wcm9jZXNzLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxnQkFBZ0IsQ0FBQztBQUV4QixPQUFPLEVBQUUsWUFBWSxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUUsVUFBVSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBRTdFLE9BQU8sRUFBRSw2QkFBNkIsRUFBaUMsTUFBTSw2QkFBNkIsQ0FBQztBQUMzRyxPQUFPLFFBQVEsTUFBTSxxQkFBcUIsQ0FBQztBQUMzQyxPQUFPLEVBQUUsZUFBZSxFQUFjLE1BQU0sTUFBTSxDQUFDO0FBQ25ELE9BQU8sRUFBRSxHQUFHLEVBQUUsSUFBSSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFM0MsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLFVBQVUsQ0FBQztBQUVwQyxPQUFPLEVBQUUsNEJBQTRCLEVBQUUsTUFBTSxXQUFXLENBQUM7Ozs7O0FBS3pELE1BQU0sQ0FBQyxNQUFNLG9CQUFvQixHQUFHLElBQUksUUFBUSxDQUFDLElBQUksQ0FBQyxvQkFBb0IsRUFBRSxDQUFDO0FBQzdFLE1BQU0sQ0FBQyxNQUFNLGtCQUFrQixHQUFHLElBQUksUUFBUSxDQUFDLElBQUksQ0FBQyxrQkFBa0IsRUFBRSxDQUFDO0FBQ3pFLE1BQU0sQ0FBQyxNQUFNLGlCQUFpQixHQUFHLElBQUksUUFBUSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsV0FBVyxDQUFDLENBQUM7QUFDOUUsTUFBTSxDQUFDLE1BQU0sbUJBQW1CLEdBQUcsSUFBSSxRQUFRLENBQUMsSUFBSSxDQUFDLG1CQUFtQixFQUFFLENBQUM7QUFDM0UsTUFBTSxDQUFDLE1BQU0sa0JBQWtCLEdBQUcsSUFBSSxRQUFRLENBQUMsSUFBSSxD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ZW50RW1pdHRlciwgZm9yd2FyZFJlZiwgSW5qZWN0LCBJbmplY3RhYmxlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBBbmd1bGFyRmlyZUF1dGggfSBmcm9tICdAYW5ndWxhci9maXJlL2NvbXBhdC9hdXRoJztcbmltcG9ydCB7IE1BVF9TTkFDS19CQVJfREVGQVVMVF9PUFRJT05TLCBNYXRTbmFja0JhciwgTWF0U25hY2tCYXJDb25maWd9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL3NuYWNrLWJhcic7XG5pbXBvcnQgZmlyZWJhc2UgZnJvbSAnZmlyZWJhc2UvY29tcGF0L2FwcCc7XG5pbXBvcnQgeyBCZWhhdmlvclN1YmplY3QsIE9ic2VydmFibGUgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IG1hcCwgdGFrZSB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcblxuaW1wb3J0IHsgQWNjb3VudHMgfSBmcm9tICcuLi9lbnVtcyc7XG5pbXBvcnQgeyBJQ3JlZGVudGlhbHMsIElTaWduSW5Qcm9jZXNzLCBJU2lnblVwUHJvY2VzcywgTmd4QXV0aEZpcmViYXNlVUlDb25maWcgfSBmcm9tICcuLi9pbnRlcmZhY2VzJztcbmltcG9ydCB7IE5neEF1dGhGaXJlYmFzZVVJQ29uZmlnVG9rZW4gfSBmcm9tICcuLi90b2tlbnMnO1xuaW1wb3J0IHsgRmlyZXN0b3JlU3luY1NlcnZpY2UgfSBmcm9tICcuL2ZpcmVzdG9yZS1zeW5jLnNlcnZpY2UnO1xuXG5pbXBvcnQgVXNlckNyZWRlbnRpYWwgPSBmaXJlYmFzZS5hdXRoLlVzZXJDcmVkZW50aWFsO1xuXG5leHBvcnQgY29uc3QgZmFjZWJvb2tBdXRoUHJvdmlkZXIgPSBuZXcgZmlyZWJhc2UuYXV0aC5GYWNlYm9va0F1dGhQcm92aWRlcigpO1xuZXhwb3J0IGNvbnN0IGdvb2dsZUF1dGhQcm92aWRlciA9IG5ldyBmaXJlYmFzZS5hdXRoLkdvb2dsZUF1dGhQcm92aWRlcigpO1xuZXhwb3J0IGNvbnN0IGFwcGxlQXV0aFByb3ZpZGVyID0gbmV3IGZpcmViYXNlLmF1dGguT0F1dGhQcm92aWRlcihcImFwcGxlLmNvbVwiKTtcbmV4cG9ydCBjb25zdCB0d2l0dGVyQXV0aFByb3ZpZGVyID0gbmV3IGZpcmViYXNlLmF1dGguVHdpdHRlckF1dGhQcm92aWRlcigpO1xuZXhwb3J0IGNvbnN0IGdpdGh1YkF1dGhQcm92aWRlciA9IG5ldyBmaXJlYmFzZS5hdXRoLkdpdGh1YkF1dGhQcm92aWRlcigpO1xuZXhwb3J0IGNvbnN0IG1pY3Jvc29mdEF1dGhQcm92aWRlciA9IG5ldyBmaXJlYmFzZS5hdXRoLk9BdXRoUHJvdmlkZXIoXG4gIFwibWljcm9zb2Z0LmNvbVwiXG4pO1xuZXhwb3J0IGNvbnN0IHlhaG9vQXV0aFByb3ZpZGVyID0gbmV3IGZpcmViYXNlLmF1dGguT0F1dGhQcm92aWRlcihcInlhaG9vLmNvbVwiKTtcblxuZXhwb3J0IGVudW0gQXV0aFByb3ZpZGVyIHtcbiAgQUxMID0gXCJhbGxcIixcbiAgQU5PTllNT1VTID0gXCJhbm9ueW1vdXNcIixcbiAgRW1haWxBbmRQYXNzd29yZCA9IFwiZmlyZWJhc2VcIixcbiAgR29vZ2xlID0gXCJnb29nbGVcIixcbiAgQXBwbGUgPSBcImFwcGxlXCIsXG4gIEZhY2Vib29rID0gXCJmYWNlYm9va1wiLFxuICBUd2l0dGVyID0gXCJ0d2l0dGVyXCIsXG4gIEdpdGh1YiA9IFwiZ2l0aHViXCIsXG4gIE1pY3Jvc29mdCA9IFwibWljcm9zb2Z0XCIsXG4gIFlhaG9vID0gXCJ5YWhvb1wiLFxuICBQaG9uZU51bWJlciA9IFwicGhvbmVOdW1iZXJcIixcbn1cblxuQEluamVjdGFibGUoe1xuICBwcm92aWRlZEluOiBcInJvb3RcIixcbn0pXG5leHBvcnQgY2xhc3MgQXV0aFByb2Nlc3NTZXJ2aWNlIGltcGxlbWVudHMgSVNpZ25JblByb2Nlc3MsIElTaWduVXBQcm9jZXNzIHtcbiAgb25TdWNjZXNzRW1pdHRlcjogRXZlbnRFbWl0dGVyPGFueT4gPSBuZXcgRXZlbnRFbWl0dGVyPGFueT4oKTtcbiAgb25FcnJvckVtaXR0ZXI6IEV2ZW50RW1pdHRlcjxhbnk+ID0gbmV3IEV2ZW50RW1pdHRlcjxhbnk+KCk7XG5cbiAgLy8gVXNlZnVsIHRvIGtub3cgYWJvdXQgYXV0aCBzdGF0ZSBldmVuIGJldHdlZW4gcmVsb2Fkcy5cbiAgLy8gUmVwbGFjZSBlbWFpbENvbmZpcm1hdGlvblNlbnQgYW5kIGVtYWlsVG9Db25maXJtLlxuICBwcml2YXRlIF91c2VyJCA9IG5ldyBCZWhhdmlvclN1YmplY3Q8ZmlyZWJhc2UuVXNlciB8IG51bGw+KG51bGwpO1xuICBnZXQgdXNlciQoKTogT2JzZXJ2YWJsZTxmaXJlYmFzZS5Vc2VyIHwgbnVsbD4ge1xuICAgIHJldHVybiB0aGlzLl91c2VyJC5hc09ic2VydmFibGUoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVwcmVjYXRlZCBhY2Nlc3MgdmlhIHVzZXIkIGFzeW5jaHJvbm91c2x5IGluc3RlYWRcbiAgICovXG4gIHVzZXI6IGZpcmViYXNlLlVzZXI7XG5cbiAgbWVzc2FnZU9uQXV0aFN1Y2Nlc3M6IHN0cmluZztcbiAgbWVzc2FnZU9uQXV0aEVycm9yOiBzdHJpbmc7XG5cbiAgLy8gTGVnYWN5IGZpZWxkIHRoYXQgaXMgc2V0IHRvIHRydWUgYWZ0ZXIgc2lnbiB1cC5cbiAgLy8gVmFsdWUgaXMgbG9zdCBpbiBjYXNlIG9mIHJlbG9hZC4gVGhlIGlkZWEgaGVyZSBpcyB0byBrbm93IGlmIHdlIGp1c3Qgc2VudCBhIHZlcmlmaWNhdGlvbiBlbWFpbC5cbiAgZW1haWxDb25maXJtYXRpb25TZW50OiBib29sZWFuO1xuICAvLyBMZWdhY3kgZmlsZWQgdGhhdCBjb250YWluIHRoZSBtYWlsIHRvIGNvbmZpcm0uIFNhbWUgbGlmZWN5Y2xlIHRoYW4gZW1haWxDb25maXJtYXRpb25TZW50LlxuICBlbWFpbFRvQ29uZmlybTogc3RyaW5nO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHB1YmxpYyBhZmE6IEFuZ3VsYXJGaXJlQXV0aCxcbiAgICBASW5qZWN0KGZvcndhcmRSZWYoKCkgPT4gTmd4QXV0aEZpcmViYXNlVUlDb25maWdUb2tlbikpXG4gICAgcHVibGljIGNvbmZpZzogTmd4QXV0aEZpcmViYXNlVUlDb25maWcsXG4gICAgcHJpdmF0ZSBzbmFja0JhcjogTWF0U25hY2tCYXIsXG4gICAgcHJpdmF0ZSBmaXJlU3RvcmVTZXJ2aWNlOiBGaXJlc3RvcmVTeW5jU2VydmljZSxcbiAgICBASW5qZWN0KE1BVF9TTkFDS19CQVJfREVGQVVMVF9PUFRJT05TKVxuICAgIHByaXZhdGUgbWF0U25hY2tCYXJDb25maWc6IE1hdFNuYWNrQmFyQ29uZmlnXG4gICkge31cblxuICBsaXN0ZW5Ub1VzZXJFdmVudHMoKSB7XG4gICAgdGhpcy5hZmEudXNlci5zdWJzY3JpYmUoKHVzZXI6IGZpcmViYXNlLlVzZXIgfCBudWxsKSA9PiB7XG4gICAgICB0aGlzLl91c2VyJC5uZXh0KHVzZXIpO1xuICAgICAgdGhpcy51c2VyID0gdXNlcjtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXNldCB0aGUgcGFzc3dvcmQgb2YgdGhlIG5neC1hdXRoLWZpcmViYXNldWktdXNlciB2aWEgZW1haWxcbiAgICpcbiAgICogQHBhcmFtIGVtYWlsIC0gdGhlIGVtYWlsIHRvIHJlc2V0XG4gICAqL1xuICBwdWJsaWMgYXN5bmMgcmVzZXRQYXNzd29yZChlbWFpbDogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnNvbGUubG9nKFwiUGFzc3dvcmQgcmVzZXQgZW1haWwgc2VudFwiKTtcbiAgICAgIHJldHVybiBhd2FpdCB0aGlzLmFmYS5zZW5kUGFzc3dvcmRSZXNldEVtYWlsKGVtYWlsKTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgcmV0dXJuIHRoaXMubm90aWZ5RXJyb3IoZXJyb3IpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBHZW5lcmFsIHNpZ24gaW4gbWVjaGFuaXNtIHRvIGF1dGhlbnRpY2F0ZSB0aGUgdXNlcnMgd2l0aCBhIGZpcmViYXNlIHByb2plY3RcbiAgICogdXNpbmcgYSB0cmFkaXRpb25hbCB3YXksIHZpYSB1c2VybmFtZSBhbmQgcGFzc3dvcmQgb3IgYnkgdXNpbmcgYW4gYXV0aGVudGljYXRpb24gcHJvdmlkZXJcbiAgICogbGlrZSBnb29nbGUsIGZhY2Vib29rLCB0d2l0dGVyIGFuZCBnaXRodWJcbiAgICpcbiAgICogQHBhcmFtIHByb3ZpZGVyIC0gdGhlIHByb3ZpZGVyIHRvIGF1dGhlbnRpY2F0ZSB3aXRoIChnb29nbGUsIGZhY2Vib29rLCB0d2l0dGVyLCBnaXRodWIpXG4gICAqIEBwYXJhbSBjcmVkZW50aWFscyBvcHRpb25hbCBlbWFpbCBhbmQgcGFzc3dvcmRcbiAgICovXG4gIHB1YmxpYyBhc3luYyBzaWduSW5XaXRoKHByb3ZpZGVyOiBBdXRoUHJvdmlkZXIsIGNyZWRlbnRpYWxzPzogSUNyZWRlbnRpYWxzKSB7XG4gICAgdHJ5IHtcbiAgICAgIGxldCBzaWduSW5SZXN1bHQ6IFVzZXJDcmVkZW50aWFsIHwgYW55O1xuXG4gICAgICBzd2l0Y2ggKHByb3ZpZGVyKSB7XG4gICAgICAgIGNhc2UgQXV0aFByb3ZpZGVyLkFOT05ZTU9VUzpcbiAgICAgICAgICBzaWduSW5SZXN1bHQgPSAoYXdhaXQgdGhpcy5hZmEuc2lnbkluQW5vbnltb3VzbHkoKSkgYXMgVXNlckNyZWRlbnRpYWw7XG4gICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgY2FzZSBBdXRoUHJvdmlkZXIuRW1haWxBbmRQYXNzd29yZDpcbiAgICAgICAgICBzaWduSW5SZXN1bHQgPSAoYXdhaXQgdGhpcy5hZmEuc2lnbkluV2l0aEVtYWlsQW5kUGFzc3dvcmQoXG4gICAgICAgICAgICBjcmVkZW50aWFscy5lbWFpbCxcbiAgICAgICAgICAgIGNyZWRlbnRpYWxzLnBhc3N3b3JkXG4gICAgICAgICAgKSkgYXMgVXNlckNyZWRlbnRpYWw7XG4gICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgY2FzZSBBdXRoUHJvdmlkZXIuR29vZ2xlOlxuICAgICAgICAgIHNpZ25JblJlc3VsdCA9IChhd2FpdCB0aGlzLmFmYS5zaWduSW5XaXRoUG9wdXAoXG4gICAgICAgICAgICBnb29nbGVBdXRoUHJvdmlkZXJcbiAgICAgICAgICApKSBhcyBVc2VyQ3JlZGVudGlhbDtcbiAgICAgICAgICBicmVhaztcblxuICAgICAgICBjYXNlIEF1dGhQcm92aWRlci5BcHBsZTpcbiAgICAgICAgICBzaWduSW5SZXN1bHQgPSAoYXdhaXQgdGhpcy5hZmEuc2lnbkluV2l0aFBvcHVwKFxuICAgICAgICAgICAgYXBwbGVBdXRoUHJvdmlkZXJcbiAgICAgICAgICApKSBhcyBVc2VyQ3JlZGVudGlhbDtcbiAgICAgICAgICBicmVhaztcblxuICAgICAgICBjYXNlIEF1dGhQcm92aWRlci5GYWNlYm9vazpcbiAgICAgICAgICBzaWduSW5SZXN1bHQgPSAoYXdhaXQgdGhpcy5hZmEuc2lnbkluV2l0aFBvcHVwKFxuICAgICAgICAgICAgZmFjZWJvb2tBdXRoUHJvdmlkZXJcbiAgICAgICAgICApKSBhcyBVc2VyQ3JlZGVudGlhbDtcbiAgICAgICAgICBicmVhaztcblxuICAgICAgICBjYXNlIEF1dGhQcm92aWRlci5Ud2l0dGVyOlxuICAgICAgICAgIHNpZ25JblJlc3VsdCA9IChhd2FpdCB0aGlzLmFmYS5zaWduSW5XaXRoUG9wdXAoXG4gICAgICAgICAgICB0d2l0dGVyQXV0aFByb3ZpZGVyXG4gICAgICAgICAgKSkgYXMgVXNlckNyZWRlbnRpYWw7XG4gICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgY2FzZSBBdXRoUHJvdmlkZXIuR2l0aHViOlxuICAgICAgICAgIHNpZ25JblJlc3VsdCA9IChhd2FpdCB0aGlzLmFmYS5zaWduSW5XaXRoUG9wdXAoXG4gICAgICAgICAgICBnaXRodWJBdXRoUHJvdmlkZXJcbiAgICAgICAgICApKSBhcyBVc2VyQ3JlZGVudGlhbDtcbiAgICAgICAgICBicmVhaztcblxuICAgICAgICBjYXNlIEF1dGhQcm92aWRlci5NaWNyb3NvZnQ6XG4gICAgICAgICAgc2lnbkluUmVzdWx0ID0gKGF3YWl0IHRoaXMuYWZhLnNpZ25JbldpdGhQb3B1cChcbiAgICAgICAgICAgIG1pY3Jvc29mdEF1dGhQcm92aWRlclxuICAgICAgICAgICkpIGFzIFVzZXJDcmVkZW50aWFsO1xuICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgIGNhc2UgQXV0aFByb3ZpZGVyLllhaG9vOlxuICAgICAgICAgIHNpZ25JblJlc3VsdCA9IChhd2FpdCB0aGlzLmFmYS5zaWduSW5XaXRoUG9wdXAoXG4gICAgICAgICAgICB5YWhvb0F1dGhQcm92aWRlclxuICAgICAgICAgICkpIGFzIFVzZXJDcmVkZW50aWFsO1xuICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgIGNhc2UgQXV0aFByb3ZpZGVyLlBob25lTnVtYmVyOlxuICAgICAgICAgIC8vIGNvbWluZyBzb29uIC0gc2VlIGZlYXR1cmUvc21zIGJyYW5jaFxuICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgICAgYCR7QXV0aFByb3ZpZGVyW3Byb3ZpZGVyXX0gaXMgbm90IGF2YWlsYWJsZSBhcyBhdXRoIHByb3ZpZGVyYFxuICAgICAgICAgICk7XG4gICAgICB9XG4gICAgICBhd2FpdCB0aGlzLmhhbmRsZVN1Y2Nlc3Moc2lnbkluUmVzdWx0KTtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIHRoaXMuaGFuZGxlRXJyb3IoZXJyKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU2lnbiB1cCBuZXcgdXNlcnMgdmlhIGVtYWlsIGFuZCBwYXNzd29yZC5cbiAgICogQWZ0ZXIgdGhhdCB0aGUgbmd4LWF1dGgtZmlyZWJhc2V1aS11c2VyIHNob3VsZCB2ZXJpZnkgYW5kIGNvbmZpcm0gYW4gZW1haWwgc2VudCB2aWEgdGhlIGZpcmViYXNlXG4gICAqXG4gICAqIEBwYXJhbSBkaXNwbGF5TmFtZSAtIHRoZSBkaXNwbGF5TmFtZSBpZiB0aGUgbmV3IG5neC1hdXRoLWZpcmViYXNldWktdXNlclxuICAgKiBAcGFyYW0gY3JlZGVudGlhbHMgZW1haWwgYW5kIHBhc3N3b3JkXG4gICAqIEByZXR1cm5zIC1cbiAgICovXG4gIHB1YmxpYyBhc3luYyBzaWduVXAoZGlzcGxheU5hbWU6IHN0cmluZywgY3JlZGVudGlhbHM6IElDcmVkZW50aWFscykge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCB1c2VyQ3JlZGVudGlhbDogVXNlckNyZWRlbnRpYWwgPSBhd2FpdCB0aGlzLmFmYS5jcmVhdGVVc2VyV2l0aEVtYWlsQW5kUGFzc3dvcmQoXG4gICAgICAgIGNyZWRlbnRpYWxzLmVtYWlsLFxuICAgICAgICBjcmVkZW50aWFscy5wYXNzd29yZFxuICAgICAgKTtcbiAgICAgIGNvbnN0IHVzZXIgPSB1c2VyQ3JlZGVudGlhbC51c2VyO1xuICAgICAgYXdhaXQgdGhpcy51cGRhdGVQcm9maWxlKGRpc3BsYXlOYW1lLCB1c2VyLnBob3RvVVJMKTtcblxuICAgICAgaWYgKHRoaXMuY29uZmlnLmVuYWJsZUZpcmVzdG9yZVN5bmMpIHtcbiAgICAgICAgYXdhaXQgdGhpcy5maXJlU3RvcmVTZXJ2aWNlLmdldFVzZXJEb2NSZWZCeVVJRCh1c2VyLnVpZCkuc2V0KHtcbiAgICAgICAgICB1aWQ6IHVzZXIudWlkLFxuICAgICAgICAgIGRpc3BsYXlOYW1lLFxuICAgICAgICAgIGVtYWlsOiB1c2VyLmVtYWlsLFxuICAgICAgICAgIHBob3RvVVJMOiB1c2VyLnBob3RvVVJMLFxuICAgICAgICB9IGFzIGZpcmViYXNlLlVzZXIpO1xuICAgICAgfVxuXG4gICAgICBpZiAodGhpcy5jb25maWcuZW5hYmxlRW1haWxWZXJpZmljYXRpb24pIHtcbiAgICAgICAgYXdhaXQgdXNlci5zZW5kRW1haWxWZXJpZmljYXRpb24oKTtcbiAgICAgIH1cblxuICAgICAgLy8gTGVnYWN5IGZpZWxkc1xuICAgICAgdGhpcy5lbWFpbENvbmZpcm1hdGlvblNlbnQgPSB0cnVlO1xuICAgICAgdGhpcy5lbWFpbFRvQ29uZmlybSA9IGNyZWRlbnRpYWxzLmVtYWlsO1xuXG4gICAgICBhd2FpdCB0aGlzLmhhbmRsZVN1Y2Nlc3ModXNlckNyZWRlbnRpYWwpO1xuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgdGhpcy5oYW5kbGVFcnJvcihlcnIpO1xuICAgIH1cbiAgfVxuXG4gIGFzeW5jIHNlbmROZXdWZXJpZmljYXRpb25FbWFpbCgpOiBQcm9taXNlPHZvaWQgfCBuZXZlcj4ge1xuICAgIGlmICghdGhpcy51c2VyKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QobmV3IEVycm9yKFwiTm8gc2lnbmVkIGluIHVzZXJcIikpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy51c2VyLnNlbmRFbWFpbFZlcmlmaWNhdGlvbigpO1xuICB9XG5cbiAgYXN5bmMgc2lnbk91dCgpIHtcbiAgICB0cnkge1xuICAgICAgYXdhaXQgdGhpcy5hZmEuc2lnbk91dCgpO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICB0aGlzLm5vdGlmeUVycm9yKGVycm9yKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVXBkYXRlIHRoZSBwcm9maWxlIChuYW1lICsgcGhvdG8gdXJsKSBvZiB0aGUgYXV0aGVudGljYXRlZCBuZ3gtYXV0aC1maXJlYmFzZXVpLXVzZXIgaW4gdGhlXG4gICAqIGZpcmViYXNlIGF1dGhlbnRpY2F0aW9uIGZlYXR1cmUgKG5vdCBpbiBmaXJlc3RvcmUpXG4gICAqXG4gICAqIEBwYXJhbSBuYW1lIC0gdGhlIG5ldyBuYW1lIG9mIHRoZSBhdXRoZW50aWNhdGVkIG5neC1hdXRoLWZpcmViYXNldWktdXNlclxuICAgKiBAcGFyYW0gcGhvdG9VUkwgLSB0aGUgbmV3IHBob3RvIHVybCBvZiB0aGUgYXV0aGVudGljYXRlZCBuZ3gtYXV0aC1maXJlYmFzZXVpLXVzZXJcbiAgICogQHJldHVybnMgLVxuICAgKi9cbiAgcHVibGljIHVwZGF0ZVByb2ZpbGUobmFtZTogc3RyaW5nLCBwaG90b1VSTDogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgcmV0dXJuIHRoaXMuYWZhLmN1cnJlbnRVc2VyLnRoZW4oKHVzZXI6IGZpcmViYXNlLlVzZXIpID0+IHtcbiAgICAgIGlmICghcGhvdG9VUkwpIHtcbiAgICAgICAgcmV0dXJuIHVzZXIudXBkYXRlUHJvZmlsZSh7IGRpc3BsYXlOYW1lOiBuYW1lIH0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIHVzZXIudXBkYXRlUHJvZmlsZSh7IGRpc3BsYXlOYW1lOiBuYW1lLCBwaG90b1VSTCB9KTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIHB1YmxpYyBwYXJzZVVzZXJJbmZvKHVzZXI6IGZpcmViYXNlLlVzZXIpOiBmaXJlYmFzZS5Vc2VySW5mbyB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHVpZDogdXNlci51aWQsXG4gICAgICBkaXNwbGF5TmFtZTogdXNlci5kaXNwbGF5TmFtZSxcbiAgICAgIGVtYWlsOiB1c2VyLmVtYWlsLFxuICAgICAgcGhvbmVOdW1iZXI6IHVzZXIucGhvbmVOdW1iZXIsXG4gICAgICBwaG90b1VSTDogdXNlci5waG90b1VSTCxcbiAgICAgIHByb3ZpZGVySWQ6XG4gICAgICAgIHVzZXIucHJvdmlkZXJEYXRhLmxlbmd0aCA+IDAgPyB1c2VyLnByb3ZpZGVyRGF0YVswXS5wcm92aWRlcklkIDogbnVsbCxcbiAgICB9O1xuICB9XG5cbiAgcHVibGljIGdldFVzZXJQaG90b1VybCgpOiBPYnNlcnZhYmxlPHN0cmluZyB8IG51bGw+IHtcbiAgICByZXR1cm4gdGhpcy5fdXNlciQucGlwZShcbiAgICAgIG1hcCgodXNlcjogZmlyZWJhc2UuVXNlciB8IG51bGwpID0+IHtcbiAgICAgICAgaWYgKCF1c2VyKSB7XG4gICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH0gZWxzZSBpZiAodXNlci5waG90b1VSTCkge1xuICAgICAgICAgIHJldHVybiB1c2VyLnBob3RvVVJMO1xuICAgICAgICB9IGVsc2UgaWYgKHVzZXIuZW1haWxWZXJpZmllZCkge1xuICAgICAgICAgIHJldHVybiB0aGlzLmdldFBob3RvUGF0aChBY2NvdW50cy5DSEVDSyk7XG4gICAgICAgIH0gZWxzZSBpZiAodXNlci5pc0Fub255bW91cykge1xuICAgICAgICAgIHJldHVybiB0aGlzLmdldFBob3RvUGF0aChBY2NvdW50cy5PRkYpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJldHVybiB0aGlzLmdldFBob3RvUGF0aChBY2NvdW50cy5OT05FKTtcbiAgICAgICAgfVxuICAgICAgfSlcbiAgICApO1xuICB9XG5cbiAgcHVibGljIGdldFBob3RvUGF0aChpbWFnZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgICByZXR1cm4gYGFzc2V0cy91c2VyLyR7aW1hZ2V9LnN2Z2A7XG4gIH1cblxuICBwdWJsaWMgc2lnbkluV2l0aFBob25lTnVtYmVyKCkge1xuICAgIC8vIHRvZG86IDMuMS4xOFxuICB9XG5cbiAgYXN5bmMgaGFuZGxlU3VjY2Vzcyh1c2VyQ3JlZGVudGlhbDogVXNlckNyZWRlbnRpYWwpIHtcblxuICAgIGlmKHRoaXMuY29uZmlnLnVzZVJhd1VzZXJDcmVkZW50aWFsKSB7XG4gICAgICB0aGlzLm9uU3VjY2Vzc0VtaXR0ZXIubmV4dCh1c2VyQ3JlZGVudGlhbCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMub25TdWNjZXNzRW1pdHRlci5uZXh0KHVzZXJDcmVkZW50aWFsLnVzZXIpO1xuICAgIH1cblxuICAgIGlmICh0aGlzLmNvbmZpZy5lbmFibGVGaXJlc3RvcmVTeW5jKSB7XG4gICAgICB0cnkge1xuICAgICAgICBhd2FpdCB0aGlzLmZpcmVTdG9yZVNlcnZpY2UudXBkYXRlVXNlckRhdGEoXG4gICAgICAgICAgdGhpcy5wYXJzZVVzZXJJbmZvKHVzZXJDcmVkZW50aWFsLnVzZXIpXG4gICAgICAgICk7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoXG4gICAgICAgICAgYEVycm9yIG9jY3VycmVkIHdoaWxlIHVwZGF0aW5nIHVzZXIgZGF0YSB3aXRoIGZpcmVzdG9yZTogJHtlfWBcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKHRoaXMuY29uZmlnLnRvYXN0TWVzc2FnZU9uQXV0aFN1Y2Nlc3MpIHtcbiAgICAgIGNvbnN0IGZhbGxiYWNrTWVzc2FnZSA9IGBIZWxsbyAke1xuICAgICAgICB1c2VyQ3JlZGVudGlhbC51c2VyLmRpc3BsYXlOYW1lID8gdXNlckNyZWRlbnRpYWwudXNlci5kaXNwbGF5TmFtZSA6IFwiXCJcbiAgICAgIH0hYDtcbiAgICAgIHRoaXMuc2hvd1RvYXN0KHRoaXMubWVzc2FnZU9uQXV0aFN1Y2Nlc3MgfHwgZmFsbGJhY2tNZXNzYWdlKTtcbiAgICB9XG4gIH1cblxuICBoYW5kbGVFcnJvcihlcnJvcjogYW55KSB7XG4gICAgdGhpcy5ub3RpZnlFcnJvcihlcnJvcik7XG4gICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gIH1cblxuICAvLyBSZWZyZXNoIHVzZXIgaW5mby4gQ2FuIGJlIHVzZWZ1bCBmb3IgaW5zdGFuY2UgdG8gZ2V0IGxhdGVzdCBzdGF0dXMgcmVnYXJkaW5nIGVtYWlsIHZlcmlmaWNhdGlvbi5cbiAgcmVsb2FkVXNlckluZm8oKSB7XG4gICAgcmV0dXJuIHRoaXMuX3VzZXIkXG4gICAgICAucGlwZSh0YWtlKDEpKVxuICAgICAgLnN1YnNjcmliZSgodXNlcjogZmlyZWJhc2UuVXNlciB8IG51bGwpID0+IHVzZXIgJiYgdXNlci5yZWxvYWQoKSk7XG4gIH1cblxuICAvLyBTZWFyY2ggZm9yIGFuIGVycm9yIG1lc3NhZ2UuXG4gIC8vIENvbnN1bWVycyBvZiB0aGlzIGxpYnJhcnkgYXJlIGdpdmVuIHRoZSBwb3NzaWJpbGl0eSB0byBwcm92aWRlIGFcbiAgLy8gZnVuY3Rpb24gaW4gY2FzZSB0aGV5IHdhbnQgdG8gaW5zdHJ1bWVudCBtZXNzYWdlIGJhc2VkIG9uIGVycm9yIHByb3BlcnRpZXMuXG4gIGdldE1lc3NhZ2VPbkF1dGhFcnJvcihlcnJvcjogYW55KSB7XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWJpdHdpc2VcbiAgICByZXR1cm4gKFxuICAgICAgZXJyb3IudG9TdHJpbmcoKSB8fCBcIlNvcnJ5LCBzb21ldGhpbmcgd2VudCB3cm9uZy4gUGxlYXNlIHJldHJ5IGxhdGVyLlwiXG4gICAgKTtcbiAgfVxuXG4gIC8vIFNob3cgYSB0b2FzdCB1c2luZyBjdXJyZW50IHNuYWNrYmFyIGNvbmZpZy4gSWYgbWVzc2FnZSBpcyBlbXB0eSwgbm8gdG9hc3QgaXMgZGlzcGxheWVkIGFsbG93aW5nIHRvIG9wdC1vdXQgd2hlbiBuZWVkZWQuXG4gIC8vIERlZmF1bHQgTWF0U25hY2tCYXJDb25maWcgaGFzIG5vIGR1cmF0aW9uLCBtZWFuaW5nIGl0IHN0YXlzIHZpc2libGUgZm9yZXZlci5cbiAgLy8gSWYgdGhhdCdzIHRoZSBjYXNlLCBhbiBhY3Rpb24gYnV0dG9uIGlzIGFkZGVkIHRvIGFsbG93IHRoZSBlbmQtdXNlciB0byBkaXNtaXNzIHRoZSB0b2FzdC5cbiAgc2hvd1RvYXN0KG1lc3NhZ2U6IHN0cmluZykge1xuICAgIGlmIChtZXNzYWdlKSB7XG4gICAgICB0aGlzLnNuYWNrQmFyLm9wZW4oXG4gICAgICAgIG1lc3NhZ2UsXG4gICAgICAgIHRoaXMubWF0U25hY2tCYXJDb25maWcuZHVyYXRpb24gPyBudWxsIDogXCJPS1wiXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIHNob3dFcnJvclRvYXN0KGVycm9yOiBhbnkpIHtcbiAgICBpZiAodGhpcy5jb25maWcudG9hc3RNZXNzYWdlT25BdXRoRXJyb3IpIHtcbiAgICAgIHRoaXMuc2hvd1RvYXN0KHRoaXMuZ2V0TWVzc2FnZU9uQXV0aEVycm9yKGVycm9yKSk7XG4gICAgfVxuICB9XG5cbiAgbm90aWZ5RXJyb3IoZXJyb3I6IGFueSkge1xuICAgIHRoaXMub25FcnJvckVtaXR0ZXIuZW1pdChlcnJvcik7XG4gICAgdGhpcy5zaG93RXJyb3JUb2FzdChlcnJvcik7XG4gIH1cbn1cbiJdfQ==