import { Injectable } from '@angular/core' ; import { Router } from '@angular/router' ; import { AngularFireAuth } from '@angular/fire/auth' ; import { AngularFirestore } from '@angular/fire/firestore' ; import { AngularFireFunctions } from '@angular/fire/functions' ; import * as firebase from 'firebase' ; import { auth , User } from 'firebase/app' ; import { from , of , Observable , Subscription } from 'rxjs' ; import { concatMap , filter , first , switchMap , tap } from 'rxjs/operators' ; import { DeviceDetectorService } from 'ngx-device-detector' ; import { LoginAuditModel , ProfileModel } from '@shared/models/index.model' ; import { ActivityService } from './activity.service' ; /**
 * Authentication service
 */ @ Injectable ( { providedIn : 'root' , } ) export class AuthenticationService { private subscriptions : Subscription [ ] = [ ] ; public isAuthenticated : boolean = false ; public profile : ProfileModel = new ProfileModel ( ) ; param activityService param afs param deviceService param fns param router param afAuth constructor ( private activityService , private afs , private deviceService , private fns , private router , public afAuth ) { this . checkAuth ( ) ; } /**
     * Checks authentication state of user
     */ public checkAuth ( ) { const subscription = this . getCurrentUser ( ) . subscribe ( ( profile ) => { this . isAuthenticated = true ; this . profile = profile ; } ) ; this . subscriptions . push ( subscription ) ; } /**
     * Find the logged in user details
     */ public getCurrentUser ( ) { return this . afAuth . authState . pipe ( filter ( ( user ) => ! ! user ) , switchMap ( ( user ) => this . getProfile ( user . uid ) ) ) ; } /**
     * Get all the logged in users list
     */ public getLogins ( ) { return this . afs . collection < ProfileModel > ( 'users' ) . doc < ProfileModel > ( this . profile . uid ) . collection < LoginAuditModel > ( 'logins' , ( ref ) => ref . orderBy ( 'date' , 'desc' ) ) . valueChanges ( ) ; } param uid public getProfile ( uid ) { return this . afs . collection < ProfileModel > ( 'users' ) . doc < ProfileModel > ( uid ) . valueChanges ( ) ; } /**
     * Login via github authentication
     */ public login ( ) { const provider = new auth . GithubAuthProvider ( ) ; provider . addScope ( 'public_repo,admin:repo_hook' ) ; const subscription = from ( this . afAuth . auth . signInWithPopup ( provider ) ) . pipe ( tap ( ( ) => this . activityService . setProgressBar ( true ) ) , filter ( ( credentials ) => ! ! credentials ) , concatMap ( ( credentials ) => from ( credentials . user . getIdTokenResult ( ) ) , ( credentials , oauth ) => ( { uid : credentials . user . uid , username : credentials . additionalUserInfo . username , name : credentials . user . displayName , email : credentials . user . email , phone : credentials . user . phoneNumber , avatarUrl : credentials . user . photoURL , oauth : { githubToken : credentials . credential . accessToken , token : oauth . token , expirationTime : oauth . expirationTime , authTime : oauth . authTime , issuedAtTime : oauth . issuedAtTime , signInProvider : oauth . signInProvider , claims : oauth . claims , } , emailVerified : credentials . user . emailVerified , creationTime : credentials . user . metadata . creationTime , lastSignInTime : credentials . user . metadata . lastSignInTime , } ) ) , concatMap ( ( profile ) => from ( this . afs . collection < ProfileModel > ( 'users' ) . doc < ProfileModel > ( profile . uid ) . set ( profile , { merge : true } ) ) , ( profile ) => profile ) , concatMap ( ( profile ) => from ( this . afs . collection < ProfileModel > ( 'users' ) . doc < ProfileModel > ( profile . uid ) . collection < LoginAuditModel > ( 'logins' ) . add ( { date : firebase . firestore . Timestamp . fromDate ( new Date ( ) ) , userAgent : this . deviceService . getDeviceInfo ( ) . userAgent , os : this . deviceService . getDeviceInfo ( ) . os , browser : this . deviceService . getDeviceInfo ( ) . browser , device : this . deviceService . getDeviceInfo ( ) . device , osVersion : this . deviceService . getDeviceInfo ( ) . os_version , browserVersion : this . deviceService . getDeviceInfo ( ) . browser_version , } ) ) , ( profile ) => this . profile = profile ) , tap ( ( profile ) : Observable < ProfileModel > => { const callable = this . fns . httpsCallable ( 'findAllUserEvents' ) ; callable ( { token : profile . oauth . githubToken , username : profile . username } ) ; return of ( profile ) ; } ) , switchMap ( ( profile ) => { const callable = this . fns . httpsCallable ( 'findAllUserRepositories' ) ; return callable ( { token : profile . oauth . githubToken } ) ; } ) ) . subscribe ( ( ) => { this . isAuthenticated = true ; this . activityService . setProgressBar ( false ) ; this . checkAuth ( ) ; } ) ; this . subscriptions . push ( subscription ) ; } /**
     * Logout from dashboard hub
     */ public logout ( ) { from ( this . afAuth . auth . signOut ( ) ) . pipe ( first ( ) ) . subscribe ( ( ) => { this . profile = new ProfileModel ( ) ; this . isAuthenticated = false ; this . subscriptions . map ( ( subscription ) => subscription . unsubscribe ( ) ) ; this . router . navigate ( [ '/' ] ) ; } ) ; } }