import { Injectable } from "@angular/core"; import { Request } from "../models/request"; import { TranslatorService } from "../translator/translator.service"; import { ConnectorService } from "../connector/connector.service"; import { Observable, throwError } from "rxjs"; import { CheckPatientRegisterationRequest } from "./models/check-patient-registeration.request"; import { LoginRequest } from "./models/login.request"; import { Response } from "../models/response"; import { AuthenticatedUser } from "./models/authenticated-user"; import { CommonService } from "../common/common.service"; import { CheckUserAuthenticationRequest } from "./models/check-user-auth.request"; import { CheckActivationCodeRequest } from "./models/check-activation-code.request"; import { CheckUserAuthenticationResponse } from "./models/check-user-auth.response"; import { CheckActivationCodeResponse } from "./models/check-activation-code.response"; import { NativeStorage } from "@ionic-native/native-storage/ngx"; import { CheckRegisterationCodeRequest } from "./models/check-registeration-code.request"; import { RegisterInformationRequest } from "./models/register-information.request"; import { ForgotFileIDResponse } from "./models/forgot-File-ID.response"; import { EmailRequest } from "../models/email-request"; import { EmailInput } from "../../ui/email/models/email-input"; import { UserLocalNotificationService } from "../user-local-notification/user-local-notification.service"; import { GetLoginInfoRequest } from "./models/get-login-info.request"; import { GetLoginInfoResponse } from "./models/get-login-info.response"; import { analyzeAndValidateNgModules } from "@angular/compiler"; import { Events } from "@ionic/angular"; import { InternationalMobileComponent } from "../../ui/mobile-number/international-mobile/international-mobile.component"; import { SMSCheckRequest } from "./models/smscheck.request"; import { SMSCheckResponse } from "./models/smscheck.response"; import { ForgetPassword } from 'src/app/authentication/models/forget.password'; @Injectable({ providedIn: "root" }) export class AuthenticationService { public static MOBILE_USER = 102; /* login methods */ public static loginURL = 'Services/Authentication.svc/REST/CheckPatientAuthentication'; public static checkUserAuthURL = 'Services/Authentication.svc/REST/CheckPatientAuthentication'; public static login = 'Services/ERP.svc/REST/MemberLogin'; public static activationCodeURL = 'Services/Authentication.svc/REST/CheckActivationCode'; public static getLoginInfoURL = 'Services/Authentication.svc/REST/GetMobileLoginInfo'; public static smsCheck='Services/ERP.svc/REST/CheckActivationCode'; public static smsCheckForget='Services/ERP.svc/REST/CheckPublicActivationCode'; public static smsSendCode='Services/ERP.svc/REST/SendPublicActivationCode'; /* register methods */ public static checkPatientForRegisterationURL = 'Services/Authentication.svc/REST/CheckPatientForRegisteration'; public static sendSmsForRegisterURL = 'Services/Authentication.svc/REST/SendSMSForPatientRegisteration'; public static registerTempUserURL = 'Services/Authentication.svc/REST/RegisterTempPatientWithoutSMS'; public static sendSMSForgotFileNoURL = 'Services/Authentication.svc/REST/SendPatientIDSMSByMobileNumber'; public static forgotFileIDURL = 'Services/Authentication.svc/REST/CheckActivationCodeForSendFileNo'; public static user: AuthenticatedUser; /*user checking methods */ public static userChecking = 'Services/ERP.svc/REST/Get_BasicUserInformation'; public static changePasswordForget ='Services/ERP.svc/REST/ChangePassword_Forget'; public static changePassword ='Services/ERP.svc/REST/ChangePassword_FromActiveSession'; public static expiredPassword = 'Services/ERP.svc/REST/ChangePassword_Expired'; public static LOGIN_EVENT = 'user-login-event'; public static FAMILY_LOGIN_EVENT = 'family-login-event'; public static AUTHENTICATED_USER_KEY = 'save-authenticated-user'; public static LOGIN_DATA="logindata"; // private static user: AuthenticatedUser; constructor( public con: ConnectorService, public cs: CommonService, public ts: TranslatorService, public nativeStorage: NativeStorage, public localNotifications: UserLocalNotificationService, private events: Events ) { } public authenticateRequest(request: Request, automaticLogin = true): Request { this.setPublicFields(request); const user = this.getAuthenticatedUser(); if (user) { request.P_SESSION_ID = user.P_SESSION_ID; request.MobileNumber = user.EMPLOYEE_MOBILE_NUMBER; request.LogInTokenID = user.LogInTokenID; request.TokenID = user.TokenID; request.P_USER_NAME = user.EMPLOYEE_NUMBER; request.UserName = user.EMPLOYEE_NUMBER; if (AuthenticationService.requireRelogin) { this.sessionTimeOutDialog(); } } else { this.cs.userNeedToReLogin(); } /* else { if (automaticLogin) { this.cs.openUserLogin(); } } */ return request; } public setPublicFields(request: Request): Request { request.VersionID = 1; request.Channel = 31; request.LanguageID = TranslatorService.getCurrentLanguageCode(); //request.IPAdress = '10.10.10.10'; //request.SessionID = "any thing"; // ??? required for not authorized login funny request.MobileType = ""; //request.isDentalAllowedBackend = false; return request; } public authenticateAndSetPersonalInformation( request: EmailRequest, examinationInfo?: any ): EmailRequest { // if not authenticated will be redirected to login this.authenticateRequest(request); const user = this.getAuthenticatedUser(); if (user) { // request.To = user.Email; // request.DateofBirth = user.DateofBirth; // request.PatientIditificationNum = user.PatientIdentificationNo; // request.PatientMobileNumber = user.MobileNo; // request.PatientName = user.PatientName; // request.PatientOutSA = user.PatientOutSA ? 1 : 0; // request.PatientTypeID = user.PatientTypeID; if (examinationInfo) { if (examinationInfo.SetupID) { request.SetupID = examinationInfo.SetupID; } if (examinationInfo.ProjectName) { request.ProjectName = examinationInfo.ProjectName; } if (examinationInfo.ClinicName) { request.ClinicName = examinationInfo.ClinicDescription; } if (examinationInfo.DoctorName) { request.DoctorName = examinationInfo.DoctorName; } if (examinationInfo.ProjectID) { request.ProjectID = examinationInfo.ProjectID; } if (examinationInfo.InvoiceNo) { request.InvoiceNo = examinationInfo.InvoiceNo; } if (examinationInfo.OrderDate) { request.OrderDate = this.cs.getDateISO( this.cs.evaluteDateAsObject(examinationInfo.OrderDate) ); } } } return request; } public getAuthenticatedRequest(login = true): Request { const request = new Request(); this.authenticateRequest(request, login); return request; } public getPublicRequest(): Request { const request = new Request(); this.setPublicFields(request); return request; } public login(request: LoginRequest, onError: any, errorLabel: string): Observable { this.setPublicFields(request); return this.con.post(AuthenticationService.login, request, onError, errorLabel); } public isAuthenticated(): boolean { return AuthenticationService.user != null; } /** * this fucntion load from user information if he logged in before * and save user into memory and local storage * disable notifications for previous user if new user logged in with different user * * * info: * 1- user stored in local storage without token * @param result check activation code result */ public setAuthenticatedUser( result: SMSCheckResponse ): Observable { return Observable.create(observer => { this.loadAuthenticatedUser().subscribe( (loadedUser: AuthenticatedUser) => { AuthenticationService.requireRelogin = false; this.startIdleMonitoring(); const user = this.updateAuthenticatedUser(result, loadedUser); /* we store in hd without token but with token in memory*/ this.saveUserInStorage(user).subscribe((success: boolean) => { AuthenticationService.user = user; this.publishUserChangeEvent(); observer.next(true); observer.complete(); }); } ); }); } public resetAuthenticatedUser(user: AuthenticatedUser) { AuthenticationService.user = user; AuthenticationService.requireRelogin = false; this.startIdleMonitoring(); this.publishUserChangeEvent(); } // public setAuthenticatedMemberFamilyUser(result: CheckActivationCodeResponse) { // const authUser = new AuthenticatedUser(); // AuthenticationService.requireRelogin = false; // this.startIdleMonitoring(); // const user = this.updateAuthenticatedUser(result, authUser); // // user["hello"]= "ok"; // /* we store in hd without token but with token in memory*/ // AuthenticationService.user = user; // this.publishFamilyMemeberUserChangeEvent(); // } public updateLoggedInUser(newUser: AuthenticatedUser): Observable { return Observable.create(observer => { /* we store in hd without token but with token in memory*/ this.saveUserInStorage(newUser).subscribe((success: boolean) => { AuthenticationService.requireRelogin = false; AuthenticationService.user = newUser; this.publishUserChangeEvent(); observer.next(success); observer.complete(); }); }); } public setDeviceToken(token: string) { const user = this.getAuthenticatedUser(); if (user) { // user.deviceToken = token; this.updateLoggedInUser(user).subscribe((success: boolean) => { // console.log('token stored:' + token); }); } } public registerTempUser( request: RegisterInformationRequest, onError: any, errorLabel: string ): Observable { this.setPublicFields(request); request.TokenID = ""; return this.con.post( AuthenticationService.registerTempUserURL, request, onError, errorLabel ); } public getLoginInfo( request: GetLoginInfoRequest, onError: any, errorLabel: string ): Observable { this.setPublicFields(request); return this.con.post( AuthenticationService.getLoginInfoURL, request, onError, errorLabel ); } /** *update new authenticated user from previously stored and loaded user */ private updateAuthenticatedUser( result: SMSCheckResponse, loadedUser: AuthenticatedUser ): AuthenticatedUser { const user = result.MemberInformationList[0]; user.P_SESSION_ID = result.P_SESSION_ID; user.MobileNumber = result.EMPLOYEE_MOBILE_NUMBER; user.TokenID = result.TokenID; user.CompanyImageDescription=result.CompanyImageDescription; user.CompanyImageURL=result.CompanyImageURL; user.LogInTokenID = this.cs.sharedService.getSharedData( AuthenticationService.LOGIN_DATA ).LogInTokenID; return user; } public isRealEmail(email: string): boolean { return EmailInput.isValidEmail(email); } public isAuthenticatedUserHasRealEmail(): boolean { const user = this.getAuthenticatedUser(); return user ? this.isRealEmail(user.EMPLOYEE_EMAIL_ADDRESS) : false; } /** * we store in localstorage without token but we keep it in the static member */ private saveUserInStorage(user: AuthenticatedUser): Observable { return Observable.create(observer => { if (user) { // const TokenID = user.TokenID; // user.TokenID = null; this.nativeStorage .setItem(AuthenticationService.AUTHENTICATED_USER_KEY, user) .then( () => { //user.TokenID = TokenID; observer.next(true); observer.complete(); }, error => { // user.TokenID = TokenID; observer.next(false); observer.complete(); } ); } else { observer.next(false); observer.complete(); } }); } /** * signout *clear user session and storage information */ public clearUser(): Observable { this.clearUserSession(); return Observable.create(observer => { this.publishUserChangeEvent(); this.nativeStorage .remove(AuthenticationService.AUTHENTICATED_USER_KEY) .then( () => { observer.next(true); observer.complete(); }, () => { observer.next(false); observer.complete(); } ); }); } private publishUserChangeEvent() { this.events.publish( AuthenticationService.LOGIN_EVENT, this.getAuthenticatedUser(), Date.now() ); } private publishFamilyMemeberUserChangeEvent() { this.events.publish( AuthenticationService.FAMILY_LOGIN_EVENT, this.getAuthenticatedUser(), Date.now() ); } public clearUserSession() { AuthenticationService.user = null; } public loadAuthenticatedUser(): Observable { return Observable.create(observer => { this.nativeStorage .getItem(AuthenticationService.AUTHENTICATED_USER_KEY) .then( user => { observer.next(user); observer.complete(); }, error => { // this.getAuthenticatedUser() //commented for now will uncomment when we are going to deploy on the device; //observer.next(null); observer.next(this.getAuthenticatedUser()); observer.complete(); } ); }); } // TODO you should read from local storage and update static member public getAuthenticatedUser(): AuthenticatedUser { /* if (AuthenticationService.requireRelogin) { this.sessionTimeOutDialog(); return new AuthenticatedUser(); } else { return AuthenticationService.user; } */ if(AuthenticationService.user){ return AuthenticationService.user; }else{ this.cs.openLogin(); } } public checkUserAuthentication(request: CheckUserAuthenticationRequest, onError: any, errorLabel: string) : Observable { this.setPublicFields(request); return this.con.post(AuthenticationService.userChecking, request, onError, errorLabel); } public checkActivationCode(request: CheckActivationCodeRequest, onError: any, errorLabel: string) : Observable { this.setPublicFields(request); return this.con.post(AuthenticationService.activationCodeURL, request, onError, errorLabel); } public checkSMS(request: SMSCheckRequest, onError: any, errorLabel: string) : Observable { this.setPublicFields(request); return this.con.post(AuthenticationService.smsCheck, request, onError, errorLabel); } public checkForgetSMS(request: SMSCheckRequest, onError: any, errorLabel: string) : Observable { this.setPublicFields(request); return this.con.post(AuthenticationService.smsCheckForget, request, onError, errorLabel); } public sendPublicSMS(request: SMSCheckRequest, onError: any, errorLabel: string) : Observable { this.setPublicFields(request); return this.con.post(AuthenticationService.smsSendCode, request, onError, errorLabel); } /* client side: id no , mobile no , zip code */ /* client side: id no , mobile no , zip code */ public sendSmsForPatientRegisteration(request: CheckPatientRegisterationRequest, onError: any, errorLabel: string) : Observable { this.setPublicFields(request); request.TokenID = ''; request.isRegister = false; return this.con.post(AuthenticationService.sendSmsForRegisterURL, request, onError, errorLabel); } public checkRegisterationActivationCode(request: CheckRegisterationCodeRequest, onError: any, errorLabel: string) : Observable { this.setPublicFields(request); return this.con.post(AuthenticationService.activationCodeURL, request, onError, errorLabel); } public sendForgetPassword(request: ForgetPassword, onError: any, errorLabel: string) : Observable { this.setPublicFields(request); return this.con.post(AuthenticationService.smsSendCode, request, onError, errorLabel); } public submitForgetPassword(request: ForgetPassword, onError: any, errorLabel: string) : Observable { this.setPublicFields(request); return this.con.post(AuthenticationService.changePasswordForget, request, onError, errorLabel); } public submitChangePassword(request: ForgetPassword, onError: any, errorLabel: string) : Observable { this.setPublicFields(request); this.authenticateRequest(request); return this.con.post(AuthenticationService.changePassword, request, onError, errorLabel); } public submitExpiredPassword(request: ForgetPassword, onError: any, errorLabel: string) : Observable { this.setPublicFields(request); return this.con.post(AuthenticationService.expiredPassword, request, onError, errorLabel); } public sendSMSForForgotFileNumber(request: CheckUserAuthenticationRequest, onError: any, errorLabel: string) : Observable { this.setPublicFields(request); request.TokenID = ''; //request.SearchType = 2; //request.isRegister = false; return this.con.post(AuthenticationService.sendSMSForgotFileNoURL, request, onError, errorLabel); } public forgotFileIdActivation(request: CheckActivationCodeRequest, onError: any, errorLabel: string) : Observable { this.setPublicFields(request); request.TokenID = ''; request.SearchType = 2; request.isRegister = false; return this.con.post(AuthenticationService.forgotFileIDURL, request, onError, errorLabel); } public isSAUDIIDValid(id: string): boolean { if (!id) { return false; } try { id = id.toString(); id = id.trim(); const returnValue = Number(id); let sum = 0; if (returnValue > 0) { const type = Number(id.charAt(0)); if (id.length !== 10) { return false; } if (type !== 2 && type !== 1) { return false; } for (let i = 0; i < 10; i++) { if (i % 2 === 0) { const a = id.charAt(i); const x = Number(a) * 2; let b = x.toString(); if (b.length === 1) { b = "0" + b; } sum += Number(b.charAt(0)) + Number(b.charAt(1)); } else { sum += Number(id.charAt(i)); } } return sum % 10 === 0; } } catch (err) {} return false; } public checkUserHasEmailDialog(): Observable { return Observable.create(observer => { if (this.isAuthenticatedUserHasRealEmail()) { const message = this.ts .trPK("general", "send-email") .replace("[0]", this.getAuthenticatedUser().EmailAddress); this.cs.presentConfirmDialog(message, () => { observer.next(); observer.complete(); }); } else { this.cs.presentConfirmDialog( this.ts.trPK("login", "enter-email"), () => { //this.cs.openPatientProfile(); observer.complete(); } ); } }); } /* user session timeout after idle for 20 Minute */ private static requireRelogin = false; public static monitorInterval_M = 20 * 60 * 1000; // public static monitorInterval_M = 15 * 1000; private static timerID; private stopIdleTimer() { if (AuthenticationService.timerID) { clearTimeout(AuthenticationService.timerID); } } private sessionTimeOutDialog() { this.cs.presentConfirmDialog( this.ts.trPK("general", "idle-relogin"), () => { // this.cs.openUserLogin(); } ); } /* reset and start idling interval */ private detectIdle() { this.stopIdleTimer(); AuthenticationService.timerID = setTimeout(() => { if (AuthenticationService.user) { AuthenticationService.requireRelogin = true; this.clearUserSession(); this.publishUserChangeEvent(); this.sessionTimeOutDialog(); this.cs.openHome(); } }, AuthenticationService.monitorInterval_M); } private registerDocumentEvents(events: string[], handler: any) { for (const event of events) { document.addEventListener(event, handler); } } private static eventsRegistered = false; public startIdleMonitoring() { if (!AuthenticationService.eventsRegistered) { AuthenticationService.eventsRegistered = true; // every time we have and event this.registerDocumentEvents( ["mousedown", "touchstart", "click", "keyup"], () => { // if user still logged in and session not expired if ( AuthenticationService.user && !AuthenticationService.requireRelogin ) { // reset and start idling timer this.detectIdle(); } } ); } } }