Untitled
unknown
plain_text
2 years ago
10 kB
12
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...