Untitled
unknown
plain_text
2 years ago
10 kB
9
Indexable
/** * TODO this service is to be deprecated. * This will be replaced by app.service */ import { HttpClient } from '@angular/common/http'; import { Inject, Injectable } from '@angular/core'; import { Auth } from 'aws-amplify'; import { BehaviorSubject, from, Observable, of } from 'rxjs'; import { map, catchError, filter, switchMap, pluck } from 'rxjs/operators'; import { Router } from '@angular/router'; import { IUser, IUserCognito, ISellerListingWithUser } from '@models'; import { APP_CONFIG, IAppConfig } from '@config'; import { AirbrakeErrorHandler } from '@core'; import { ChatKittyService } from './chatKitty.service'; import { SellerListingService } from './seller-listing.service'; import { HelperService } from './helper.service'; import { IAppUser } from '@app/app.model'; @Injectable({ providedIn: 'root' }) export class UsersService { private readonly userSubject = new BehaviorSubject<IUser>(null); private readonly userFavSubject = new BehaviorSubject<ISellerListingWithUser[]>([]); private readonly cognitoDataSubject = new BehaviorSubject<any>({ accessToken: '', idToken: '', exp: null, }); private readonly baseUrl: string; private favIds: string[] = []; private favs: ISellerListingWithUser[] = []; constructor( private readonly http: HttpClient, private readonly chatKittyService: ChatKittyService, private readonly sellerListingService: SellerListingService, private readonly helperService: HelperService, private readonly router: Router, @Inject(APP_CONFIG) private readonly config: IAppConfig, private readonly errorHandler: AirbrakeErrorHandler ) { this.baseUrl = `${this.config.apiUrl}/manage/users`; } get cognitoData(): Observable<any> { return this.cognitoDataSubject.asObservable(); } get user() { return this.userSubject.asObservable().pipe(filter(Boolean)) as Observable<IUser>; } get favorites() { return this.userFavSubject.asObservable(); } get userStateWithNull() { return this.userSubject.asObservable(); } me() { return this.http.get<IAppUser>(`${this.baseUrl}/me`); } // TODO is now done in the backend getVerificationDetails(user): IUser { if (!user) { return null; } const { userDetails, verification } = user; const isEmailVerified = user.verification.email; const isPhoneVerified = verification ? !!verification.phone : false; const isLicenseVerified = verification ? !!verification.vouched : false; const isBankConnected = !!(userDetails.agreementNumber || verification.bank); const isVerified = !!(isEmailVerified && isPhoneVerified && isLicenseVerified && isBankConnected); return { ...user, verification: { ...verification, isEmailVerified, isPhoneVerified, isLicenseVerified, isBankConnected, isVerified, }, }; } /** * TODO below are not used yet * backup purposes for now * */ getUserDealContacts(id) { return this.http.get(`${this.baseUrl}/${id}/deals/contacts`); } editUsers(data) { return this.http.put(`${this.baseUrl}`, data); } // updateEmail(data) { // return this.http.put(`${this.baseUrl}/email`, data); // } updateDriverLicense(data) { return this.http.put(`${this.baseUrl}/license`, data); } updateNotifications(data) { return this.http.put(`${this.baseUrl}/notifications`, data); } updateVerification(data) { return this.http.put(`${this.baseUrl}/verification`, data); } // updateProfile(data) { // return this.http.put(`${this.baseUrl}/profile`, data); // } updatePhone(data) { return this.http.post<any>(`${this.baseUrl}/phone`, data); } verifyPhone(data) { return this.http.put<any>(`${this.baseUrl}/phone`, data); } forgotPassword(email: string) { return this.http.post<any>(`${this.baseUrl}/forgot-password`, { email }); } resetPassword(params: { code: string; email: string; password: string }) { return this.http.put<any>(`${this.baseUrl}/reset-password`, params); } resendPhoneCode() { return this.http.get<any>(`${this.baseUrl}/phone`); } confirmEmail(data: { code: string }) { return this.http.post<any>(`${this.baseUrl}/confirm-email`, data); } sendVerification() { return this.http.post<any>(`${this.baseUrl}/email/send-verification`, {}); } getCurrentProfile() { return from(Auth.currentSession()).pipe( switchMap(() => this.me()), switchMap((user) => this.getAwsProfile().pipe(map((cognito) => ({ ...user, cognito })))), switchMap((user) => this.configureUser(user)), map((user: IUser) => { if (user.verification?.bank !== user.verification.isBankConnected) { this.updateVerification({ bank: user.verification.isBankConnected, }).subscribe(); } this.userSubject.next(user); // TODO admin has no favs // this.getFavs() // .pipe( // pluck('data'), // map((favs: { _id: string; favorites: IFavItem[] }) => { // this.favIds = favs.favorites.map((fav) => fav.listingId?._id); // this.favs = favs.favorites.map((fav) => fav.listingId); // return this.userFavSubject.next(this.favs); // }) // ) // .subscribe(); return user; }), catchError((err) => { this.userSubject.next(null); this.cognitoDataSubject.next({ accessToken: '', idToken: '', exp: null }); this.errorHandler.handleError(err); return of(null); }) ); } getAwsProfile() { return this.cognitoData.pipe( switchMap((cognitoData) => { const hostedUiData = this.getHostedUIData(); if (hostedUiData.accessToken) { this.cognitoDataSubject.next(hostedUiData); } if (cognitoData?.accessToken) { return this.cognitoData; } return new Observable((observer) => { const abortController = new AbortController(); const subscription = from(Auth.currentAuthenticatedUser({ bypassCache: true })).subscribe(observer); return () => { abortController.abort(); subscription.unsubscribe(); }; }); }) ) as Observable<IUserCognito>; } signOut() { Auth.signOut({ global: true }).then(() => { localStorage.clear(); this.helperService.deleteCookies(); this.userSubject.next(null); this.chatKittyService.closeUserSession(); this.sellerListingService.clearListingCache(); this.router.navigate(['/auth/login']); }); } getUserApplicationData() { this.user .pipe // TODO refine // tap((user: IUser) => { // this.oneSignalService.setExternalUserId(user?._id); // }), // tap((user: IUser) => { // this.chatKittyService.startUserSession(user); // }), // switchMap((user) => { // if (user.userDetails.personNumber && user.userDetails.agreementNumber) { // return this.usallianceService.getAccount(); // } // return of(null); // }) () .subscribe(); } processCognitoCallback(url) { const parameter = url.split('&'); const idToken = parameter[0].split('=')[1]; const accessToken = parameter[1].split('=')[1]; const exp = parameter[2].split('=')[1]; this.setHostedUIData({ accessToken, idToken, exp }); this.cognitoDataSubject.next({ accessToken, idToken, exp: Date.now() + exp * 100 }); } setHostedUIData({ accessToken, idToken, exp }) { sessionStorage.setItem('hostedUI_access_token', accessToken); sessionStorage.setItem('hostedUI_id_token', idToken); sessionStorage.setItem('hostedUI_exp', String(Date.now() + exp * 100)); } getHostedUIData(): { idToken: string; accessToken: string; exp: number } { const data = { accessToken: sessionStorage.getItem('hostedUI_access_token') || '', idToken: sessionStorage.getItem('hostedUI_id_token') || '', exp: Number(sessionStorage.getItem('hostedUI_exp')) || null, }; if (Number(data.exp) - Date.now() > 0) { return data; } sessionStorage.setItem('hostedUI_access_token', ''); sessionStorage.setItem('hostedUI_id_token', ''); sessionStorage.setItem('hostedUI_exp', null); return { accessToken: '', idToken: '', exp: null, }; } // Set user's data configureUser(rawUser): Observable<IUser> { return of(rawUser).pipe( map((user) => this.getVerificationDetails(user)), map((user) => this.setShortName(user)) ); } setShortName(user: IUser): IUser { const { firstName, lastName, nickname } = user.userDetails; const shortName = (nickname || firstName) && lastName ? `${nickname || firstName} ${lastName.charAt(0)}.` : 'User name not set'; const userDetails = { ...user.userDetails, shortName }; return { ...user, userDetails }; } public getFavs(): Observable<ISellerListingWithUser[]> { return this.http.get(`${this.baseUrl}/fav`) as Observable<ISellerListingWithUser[]>; } public processFav(listingId) { if (this.favIds.indexOf(listingId) >= 0) { this.removeFav(listingId); } else { this.addFav(listingId); } } public addFav(listingId) { this.http .post(`${this.baseUrl}/fav`, { listingId }) .pipe(pluck('data')) .subscribe((res: any) => { this.favIds = res.favorites.map((fav) => fav.listingId?._id); this.favs = res.favorites.map((fav) => fav.listingId); this.userFavSubject.next(this.favs); }); } public removeFav(listingId) { return this.http .delete(`${this.baseUrl}/fav`, { params: { listingId } }) .pipe(pluck('data')) .subscribe((res: any) => { this.favIds = res.favorites.map((fav) => fav.listingId?._id); this.favs = res.favorites.map((fav) => fav.listingId); this.userFavSubject.next(this.favs); }); } }
Editor is loading...