import { Injectable } from '@angular/core' ; import { Observable , of } from 'rxjs' ; import { map , switchMap , take } from 'rxjs/operators' ; import { snapshotToValue } from '../rx/snapshotToValue' ; import { AuthService } from '../auth' ; import { DbRefBuilder } from '../firebase/db-ref-builder' ; import { LoginUser , User } from '../models/user' ; import { Execution } from '../models/execution' ; import { PlanId } from '@machinelabs/models' ; import { Lang } from '../util/lang' ; export const PLACEHOLDER_USERNAME = 'Unnamed User' ; @ Injectable ( ) export class UserService { constructor ( private db , private authService ) { } createUserIfMissing ( ) { return this . authService . requireAuthOnce ( ) . pipe ( switchMap ( ( user ) => this . db . userRef ( user . uid ) . onceValue ( ) . pipe ( snapshotToValue , map ( existingUser => ( { existingUser , user } ) ) ) ) , switchMap ( data => ! data . existingUser || this . isDifferent ( data . user , data . existingUser ) ? this . saveUser ( this . mapLoginUserToUser ( data . user ) ) : of ( data . existingUser ) ) ) ; } private isDifferent ( loginUser , user ) { return Lang . isDifferent ( user . email , loginUser . email ) || Lang . isDifferent ( user . isAnonymous , loginUser . isAnonymous ) ; } userHasProviderData ( loginUser ) { return loginUser . providerData && loginUser . providerData . length ; } getDisplayName ( loginUser ) { return this . userHasProviderData ( loginUser ) ? loginUser . providerData [ 0 ] . displayName : loginUser . displayName ; } getPhotoUrl ( loginUser ) { return this . userHasProviderData ( loginUser ) ? loginUser . providerData [ 0 ] . photoURL : loginUser . photoURL ; } mapLoginUserToUser ( fromUser ) { return { id : fromUser . uid , displayName : this . getDisplayName ( fromUser ) || PLACEHOLDER_USERNAME , email : fromUser . email , bio : '' , isAnonymous : fromUser . isAnonymous , photoUrl : this . getPhotoUrl ( fromUser ) } ; } saveUser ( user ) { return this . authService . requireAuthOnce ( ) . pipe ( switchMap ( _ => this . db . userRef ( user . id ) . set ( user ) ) , map ( _ => user ) ) ; } updateUser ( user ) { return this . authService . requireAuthOnce ( ) . pipe ( switchMap ( _ => this . db . userRef ( user . id ) . update ( user ) ) , map ( _ => user ) ) ; } getUser ( id ) { return this . authService . requireAuthOnce ( ) . pipe ( switchMap ( _ => this . db . userRef ( id ) . onceValue ( ) ) , snapshotToValue ) ; } getCurrentUser ( ) { return this . observeUserChanges ( ) . pipe ( take ( 1 ) ) ; } observeUserChanges ( ) { return this . authService . requireAuth ( ) . pipe ( map ( loginUser => this . mapLoginUserToUser ( loginUser ) ) ) ; } isLoggedInUser ( id ) { return this . authService . requireAuthOnce ( ) . pipe ( map ( sessionUser => id === sessionUser . uid ) ) ; } userOwnsLab ( user , lab ) { return lab && user && lab . user_id === user . id ; } userOwnsExecution ( user , execution ) { return user && user . id === execution . user_id ; } getUserPlan ( ) { return this . getCurrentUser ( ) . pipe ( switchMap ( user => this . db . userPlansRef ( user . id ) . onceValue ( ) ) , snapshotToValue ) ; } }