using Clinical6SDK; using Clinical6SDK.Helpers; using Clinical6SDK.Models; using Clinical6SDK.Services; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.Diagnostics.Contracts; using System.Linq; using System.Text.Json; using System.Text.RegularExpressions; using System.Threading.Tasks; using System.Windows.Input; using Xamarin.Forms.Clinical6.Core; using Xamarin.Forms.Clinical6.Core.Helpers; using Xamarin.Forms.Clinical6.Core.Models; using Xamarin.Forms.Clinical6.Core.Services; using Xamarin.Forms.Clinical6.Core.ViewModels; using Xamarin.Forms.Clinical6.Helpers; using Xamarin.Forms.Clinical6.Services; using Xamarin.Forms.Clinical6.Views; namespace Xamarin.Forms.Clinical6.ViewModels { /// /// Login PMAV iew model. /// public class LoginPMAViewModel : BaseViewModel { // parameters public readonly IUserService _userService; public readonly IDialogService _dialogService; public readonly ICacheService _cacheService; public readonly IDeviceInfoService _deviceService; private readonly ILanguageService _languageService; private readonly IPolicyVerificationService _policyVerificationService; private readonly IBiometricsService _biometricsService; // constructed public Clinical6Instance _clinical6; public readonly IClinical6MobileUserService _mobileUserService; public ActionTracker LoginAction { get; } public ActionTracker ForgotPinAction { get; } public ActionTracker LoadSSOProvidersAction { get; } public ActionTracker BiometricsAction { get; } //public override BusyTracker PageBusy => LoginAction; public Regex ValidPinPattern = new Regex(@"^[a-zA-Z0-9@#$%*():;""""'/?!+=_-]{8,}$"); private string _emailAddress; private string _password; public bool _emailError = false; public bool _passError = false; private string _emailErrorMessage = "LoginPMAViewModelEmailReqText".Localized(); private List _optionsSSO; private int _invalidCredentials = 3; private int _tappedCount = 0; private bool canBiometricsAuthenticate; private bool _isFormEnabled = true; public LocalAuthenticationType biometricType; public ICommand OnEndpointChangeCommand => new Command(async () => await EndpointChangeTapped()); public new ICommand OnPolicyCommand { get { return new Command(async () => { await ShowPoliciesAsync(); }); } } public new string AppVersion { get { return string.Format("VersionFormatText".Localized(), _deviceService.AppVersion); } } public Action CallBackDisplayEndpoints { get; set; } public LoginPMAViewModel(INavigationService navigationService, IUserService userService, IDialogService dialogService, ICacheService cacheService, ILanguageService languageService, IDeviceInfoService deviceService, IPolicyVerificationService policyVerificationService, IBiometricsService biometricsService) : base(navigationService) { _userService = userService; _dialogService = dialogService; _cacheService = cacheService; _deviceService = deviceService; _languageService = languageService; _policyVerificationService = policyVerificationService; _biometricsService = biometricsService; _clinical6 = new Clinical6Instance(); _mobileUserService = new Clinical6MobileUserService(); LoginAction = new ActionTracker(TryLogin, CanLogin2, null); ForgotPinAction = new ActionTracker(ForgotPinTask, onError: ActionTracker.IgnoreErrors); LoadSSOProvidersAction = new ActionTracker(LoadSSOProvidersTask, onError: ActionTracker.IgnoreErrors); BiometricsAction = new ActionTracker(BiometricsTask, onError: ActionTracker.IgnoreErrors); //biometricType = _biometricsService.CanAuthenticationWith(); } public async Task InitializeAsync() { biometricType = _biometricsService.CanAuthenticationWith(); // Raise property changed if using INotifyPropertyChanged } public virtual async Task RefreshScreen() { //canBiometricsAuthenticate = await MainService.BiometricsServiceInstance.CanAuthenticate(false); canBiometricsAuthenticate = await _biometricsService.CanAuthenticate(false); //biometricType = MainService.BiometricsServiceInstance.CanAuthenticationWith(); biometricType = _biometricsService.CanAuthenticationWith(); if (!canBiometricsAuthenticate) { biometricType = LocalAuthenticationType.None; } OnPropertyChanged(nameof(IsBiometricsIconAvailable)); OnPropertyChanged(nameof(ImageBiometrics)); } //public virtual async Task RefreshScreen() //{ // if (MainService?.BiometricsServiceInstance == null) // { // canBiometricsAuthenticate = false; // biometricType = LocalAuthenticationType.None; // return; // } // canBiometricsAuthenticate = await MainService.BiometricsServiceInstance.CanAuthenticate(false); // biometricType = MainService.BiometricsServiceInstance.CanAuthenticationWith(); // if (!canBiometricsAuthenticate) // { // biometricType = LocalAuthenticationType.None; // } // OnPropertyChanged(nameof(IsBiometricsIconAvailable)); // OnPropertyChanged(nameof(ImageBiometrics)); //} /// /// Inits the implementation. /// /// The implementation. protected override async Task InitImplementation() { EmailAddress = await _userService.GetRegisteredEmail(); PassError = false; EmailError = false; #if DEBUG #endif await RefreshScreen(); await LoadSSOProvidersAction.Run(); } ////////////////////////////////////////////////// Email / Password BEGIN /// /// Gets or sets the email address. /// /// The email address. public virtual string EmailAddress { get => _emailAddress; set { if (value == _emailAddress) return; _emailAddress = value; CheckEmailError(); LoginAction.Command.ChangeCanExecute(); OnPropertyChanged(nameof(EmailAddress)); } } public virtual string Password { get => _password; set { if (value == _password) return; _password = value; CheckPasswordError(); LoginAction.Command.ChangeCanExecute(); OnPropertyChanged(nameof(Password)); OnPropertyChanged(nameof(Opacity)); } } public virtual string ImageBiometrics { get { var isBiometricsActive = false; if (Settings.GetBoleanProperty(Settings.IsBiometricsActive)) { isBiometricsActive = Settings.GetBoleanProperty(Settings.IsBiometricsActive); } if (MainService.Instance.IsBiometricsEnabled && isBiometricsActive && biometricType != LocalAuthenticationType.None) { return biometricType == LocalAuthenticationType.BiometryFaceID ? "bio_face_id_entry" : biometricType == LocalAuthenticationType.BiometryTouchID_Or_Fingerprint ? "bio_fingerprint_entry_android" : "bio_fingerprint_entry_ios"; } return string.Empty; } } public virtual bool IsBiometricsIconAvailable { get { var isBiometricsActive = false; if (Settings.GetBoleanProperty(Settings.IsBiometricsActive)) { isBiometricsActive = Settings.GetBoleanProperty(Settings.IsBiometricsActive); } if (canBiometricsAuthenticate && isBiometricsActive) { return true; } return false; } } public string Opacity { get { if (!string.IsNullOrEmpty(Password)) { return "1.0"; } return "0.5"; } } public virtual string EmailErrorMessage { get => _emailErrorMessage; set { if (value == _emailErrorMessage) return; _emailErrorMessage = value; OnPropertyChanged(nameof(EmailErrorMessage)); } } public virtual bool EmailError { get => _emailError; set { _emailError = value; OnPropertyChanged(nameof(EmailError)); } } public virtual bool PassError { get => _passError; set { _passError = value; OnPropertyChanged(nameof(PassError)); } } public virtual string EmailErrorMatBorderColor { get { var key = !EmailError ? "NormalBorderColor" : "ErrorBorderColor"; return AppHelpers.GetResource(key).ToString(); } } public virtual string PasWordErrorMatBorderColor { get { var key = !PassError ? "NormalBorderColor" : "ErrorBorderColor"; return AppHelpers.GetResource(key).ToString(); } } public virtual string CanLoginErrorText { get => CanLogin ? "SignInReadyHelpText".Localized() : "SignInErrorHelpText".Localized(); } public virtual bool CanLogin { get => !(EmailError || PassError || string.IsNullOrEmpty(EmailAddress) || string.IsNullOrEmpty(Password)); } public virtual bool CanLogin2() { return CanLogin; } // This gets called with every change to email field. public void CheckEmailError() { if (!VerifyEmail(EmailAddress)) { EmailError = true; EmailErrorMessage = string.IsNullOrEmpty(EmailAddress) ? "LoginPMAViewModelEmailReqText".Localized() : "LoginPMAViewModelInvalidEmailText".Localized(); } else { EmailError = false; EmailErrorMessage = ""; } OnPropertyChanged(nameof(EmailErrorMatBorderColor)); OnPropertyChanged(nameof(CanLogin)); OnPropertyChanged(nameof(CanLoginErrorText)); } // This gets called with every change to password field. // NOTE: More stringent password requirements could be added here. public void CheckPasswordError() { if (string.IsNullOrEmpty(Password)) { PassError = true; } else { PassError = false; } OnPropertyChanged(nameof(PasWordErrorMatBorderColor)); OnPropertyChanged(nameof(CanLogin)); OnPropertyChanged(nameof(CanLoginErrorText)); } /// /// Verifies the email. /// /// true, if email was verifyed, false otherwise. /// Email. //public bool VerifyEmail(string email) //{ // var lowerEmail = email.ToLower(); // Regex regex = new Regex(@"^(?("")("".+?(? OptionsSSO { get => _optionsSSO; set { if (value == _optionsSSO) return; _optionsSSO = value; OnPropertyChanged(nameof(OptionsSSO)); } } public bool IsFormEnabled { get => _isFormEnabled; set { if (value == _isFormEnabled) return; _isFormEnabled = value; OnPropertyChanged(nameof(IsFormEnabled)); } } /// /// Forgots the pin task. /// /// The pin task. private async Task ForgotPinTask() { await Navigation.Push(); } private async Task BiometricsTask() { var isBiometricsActive = false; if (Settings.GetBoleanProperty(Settings.IsBiometricsActive)) { isBiometricsActive = Settings.GetBoleanProperty(Settings.IsBiometricsActive); } if (MainService.Instance.IsBiometricsEnabled && isBiometricsActive) { //var canAuthenticate = await MainService.BiometricsServiceInstance.CanAuthenticate(false); var canAuthenticate = await _biometricsService.CanAuthenticate(false); if (canAuthenticate) { _biometricsService.AuthenticateUser(OnAuthComplete); //MainService.BiometricsServiceInstance.AuthenticateUser(OnAuthComplete); } } } private async void OnAuthComplete(bool sucess, string errorMessage) { Settings.SetBoleanProperty(Settings.AutomaticLogin, sucess); if (sucess) { try { EmailAddress = await SecureStorage.GetAsync(Settings.BiometricsEmail); Password = await SecureStorage.GetAsync(Settings.BiometricsPin); if (!string.IsNullOrEmpty(EmailAddress) && !string.IsNullOrEmpty(Password)) { await LoginAction.Run(); return; } } catch (Exception ex) { Console.WriteLine(ex); } } if (string.IsNullOrEmpty(errorMessage)) { errorMessage = "InvalidCredentialsBody".Localized(); } return; } /// /// Loads the SSOP roviders task. /// /// The SSOP roviders task. private async Task LoadSSOProvidersTask() { Contract.Ensures(Contract.Result() != null); var SsoOptionsList = await _userService.GetSSOProvidersAsync(); var optionsSSO = SsoOptionsList.Where(c => c.UserType == "MobileUser"); if (optionsSSO != null) { OptionsSSO = optionsSSO.OrderBy(c => c.Name).ToList(); } Console.WriteLine(SsoOptionsList.ToString()); } /// /// Checks the email. /// /// The email. public virtual async Task TryLogin() { IsFormEnabled = false; try { var email = EmailAddress; var access = Connectivity.NetworkAccess; if (access != NetworkAccess.Internet && access != NetworkAccess.ConstrainedInternet) { //await Navigation.Push(); await Navigation.Push(); IsFormEnabled = true; return; } // Apps can provide a dictionary of environment mapped logins. These are email addresses that, when used for login, // will force the app to use a specific environment. This is useful for providing "dummy" logins to apps that normally // point to production, but that aren't real users and should not trigger any data collection on the prod environment. Dictionary environmentMappedLogins = Settings.GetDictProperty(Settings.EnvironmentMappedLogins); if (environmentMappedLogins != null && environmentMappedLogins.ContainsKey(email)) { string mappedEnv = environmentMappedLogins[email]; string apiRoot = $"https://{mappedEnv}.clinical6.com/"; await UpdateEndPointAsync(apiRoot); } var status = await _userService.GetRegistrationStatus(email); //status = RegistrationStatus.Existing; //TODO this should be removed after BE guy return if (status == RegistrationStatus.New) { //if (Application.Current.Properties.ContainsKey(Settings.PinResetEmail)) if (!string.IsNullOrEmpty(Preferences.Get(Settings.PinResetEmail, null))) { //var usermail = Application.Current.Properties[Settings.PinResetEmail].ToString(); var usermail = Preferences.Get(Settings.PinResetEmail, string.Empty); if (email == usermail) { status = RegistrationStatus.Existing; } } } switch (status) { case RegistrationStatus.Withdrawn: await Navigation.Push(); IsFormEnabled = true; return; case RegistrationStatus.Disabled: await Navigation.Push(); IsFormEnabled = true; return; case RegistrationStatus.Invalid: await _dialogService.ShowAlert("EmailEntryInvalidEmailTitle".Localized(), "EmailEntryInvalidEmailMessage".Localized()); IsFormEnabled = true; return; case RegistrationStatus.New: await _dialogService.ShowAlert("InvalidCredentialsTitle".Localized(), "InvalidCredentialsBody".Localized()); IsFormEnabled = true; return; case RegistrationStatus.Existing: case RegistrationStatus.Consent: await _userService.SaveRegisteredEmail(email); await _userService.SaveTermsOfUseAccepted(true); await _userService.SaveHasPin(true); await Login(); return; } } catch (Exception exc) { Console.WriteLine($"TryLogin Exception: {exc}"); IsFormEnabled = true; await Navigation.StartLogin(); } finally { IsFormEnabled = true; } } /// /// Login this instance. /// /// The login. public virtual async Task Login() { var email = EmailAddress; var pin = Password; var responseServer = await _userService.ValidateEmailAndPinWitErrorResponse(email, pin); if (responseServer.Success) { try { await SaveEmailToSecureStorage(email); await SecureStorage.SetAsync(Settings.AppPin, pin); await SecureStorage.SetAsync(Settings.BiometricsEmail, EmailAddress); await SecureStorage.SetAsync(Settings.BiometricsPin, pin); await SecureStorage.SetAsync(Settings.UserPin, pin); } catch (Exception exc) { Console.WriteLine($"Error saving to secure storage: {exc}"); } var result = await GetUserProfile(); try { _clinical6.User = await _mobileUserService.GetProfile(_clinical6.User); } catch (Exception exc) { Console.WriteLine($"_mobileUserService.GetProfile Exception: {exc}"); } if (result != null) { var consentStatus = string.IsNullOrEmpty(Settings.GetProperty(Settings.ConsetStatus)) ? "consent_not_complete" : Settings.GetProperty(Settings.ConsetStatus); var counterSigned = consentStatus.ToLower() == "consent_complete" ? true : false; Preferences.Set(Settings.SiteMember, _clinical6.User?.SiteMember?.Id ?? 0); //Application.Current.Properties[Settings.SiteMember] = _clinical6.User?.SiteMember?.Id; if (!MainService.Instance.IsCheckCosentEnabled) { counterSigned = true; } var mobileUser = result.User; await UpdateLanguage(mobileUser?.Profile); var isPolicyDocumentsValid = true; #if DEBUG isPolicyDocumentsValid = await _policyVerificationService.VerifyPolicyDocuments(mobileUser); #else isPolicyDocumentsValid = await _policyVerificationService.VerifyPolicyDocuments(mobileUser); #endif if (!isPolicyDocumentsValid) { await Navigation.Push(); UpdateDevice(); } else if (!counterSigned) { // This is no longer used. //await Navigation.Push(consentStatus); } else { await UpdateTimeZone(result.User); UpdateDevice(); Settings.SetProperty(Settings.SleepTime, DateTime.UtcNow.Ticks.ToString()); var master = MainService.HomePage.Value as DashboardMasterPage; if (master != null) { master.IsPresented = false; } //if (Device.RuntimePlatform == Device.Android) if (DeviceInfo.Platform == DevicePlatform.Android) { Settings.SetBoleanProperty(Settings.AutomaticLogin, true); } var isBiometricsActive = false; if (Settings.GetBoleanProperty(Settings.IsBiometricsActive)) { isBiometricsActive = Settings.GetBoleanProperty(Settings.IsBiometricsActive); } //var canAuthenticate = await MainService.BiometricsServiceInstance.CanAuthenticate(false); var canAuthenticate = await _biometricsService.CanAuthenticate(false); var isBiometricsAlreadySetup = false; if (Settings.GetBoleanProperty(Settings.IsBiometricsAlreadySetup)) { isBiometricsAlreadySetup = Settings.GetBoleanProperty(Settings.IsBiometricsAlreadySetup); } Debug.WriteLine("MainService.Instance.IsBiometricsEnabled:>>" + MainService.Instance.IsBiometricsEnabled); Debug.WriteLine("!isBiometricsActive:>>" + !isBiometricsActive); Debug.WriteLine("canAuthenticate:>>" + canAuthenticate); Debug.WriteLine("!isBiometricsAlreadySetup:>>" + !isBiometricsAlreadySetup); if (MainService.Instance.IsBiometricsEnabled && !isBiometricsActive && canAuthenticate && !isBiometricsAlreadySetup) { var initSettings = new BiometricsSettingsInitValues(); initSettings.CallBackOnNotNow += async delegate { initSettings.CallBackOnNotNow = null; initSettings.CallBackBiometricsSucess = null; await Navigation.StartMainApp(MainService.HomePage.Value); }; initSettings.CallBackBiometricsSucess += async delegate (bool sucess) { await Navigation.StartMainApp(MainService.HomePage.Value); initSettings.CallBackOnNotNow = null; initSettings.CallBackBiometricsSucess = null; }; await Navigation.PushModal(initSettings); } else { await Navigation.StartMainApp(MainService.HomePage.Value); } } } else { UpdateDevice(); var master = MainService.HomePage.Value as DashboardMasterPage; master.IsPresented = false; //if (Device.RuntimePlatform == Device.Android) if (DeviceInfo.Platform == DevicePlatform.Android) { Settings.SetBoleanProperty(Settings.AutomaticLogin, true); } var isBiometricsActive = false; if (Settings.GetBoleanProperty(Settings.IsBiometricsActive)) { isBiometricsActive = Settings.GetBoleanProperty(Settings.IsBiometricsActive); } var isBiometricsAlreadySetup = false; if (Settings.GetBoleanProperty(Settings.IsBiometricsAlreadySetup)) { isBiometricsAlreadySetup = Settings.GetBoleanProperty(Settings.IsBiometricsAlreadySetup); } if (MainService.Instance.IsBiometricsEnabled && !isBiometricsActive && !isBiometricsAlreadySetup) { var initSettings = new BiometricsSettingsInitValues(); initSettings.CallBackOnNotNow += async delegate { initSettings.CallBackOnNotNow = null; initSettings.CallBackBiometricsSucess = null; await Navigation.StartMainApp(MainService.HomePage.Value); }; initSettings.CallBackBiometricsSucess += async delegate (bool sucess) { await Navigation.StartMainApp(MainService.HomePage.Value); initSettings.CallBackOnNotNow = null; initSettings.CallBackBiometricsSucess = null; }; await Navigation.PushModal(initSettings); } else { await Navigation.StartMainApp(MainService.HomePage.Value); } } } else { IsFormEnabled = true; if (checkMessageIfUserMustResetPassword(responseServer.ErrorMessage)) { await Navigation.Push(); } else if (checkMessageIfPasswordInvalid(responseServer.ErrorMessage)) { _invalidCredentials--; if (_invalidCredentials == 0) { await Navigation.Push(); return; } await _dialogService.ShowAlert("LoginPMAViewModelAlertHeaderText".Localized(), "LoginPMAViewModelRemainingAtemptTextBody".Localized()); } else if (checkMessageIfAccountIsLocked(responseServer.ErrorMessage)) { await Navigation.Push(); } else if (checkMessageIfAccountIsDisabled(responseServer.ErrorMessage)) { await Navigation.Push(); } else if (checkMessageIfUserWithdrawnFromStudy(responseServer.ErrorMessage)) { await Navigation.Push(); } else { await _dialogService.ShowAlert("InvalidCredentials".Localized(), responseServer.ErrorMessage); } } } public async Task UpdateTimeZone(User profile) { try { if (profile != null) { var userProfile = profile; var timeZoneId = DependencyService.Get().GetTimeZoneId();//Foundation.NSTimeZone.LocalTimeZone.Name; var currentTimeZone = TimeZoneInfo.FindSystemTimeZoneById(timeZoneId); if (currentTimeZone == null) { currentTimeZone = TimeZoneInfo.GetSystemTimeZones().Where(c => c.BaseUtcOffset == TimeZoneInfo.Local.BaseUtcOffset && c.StandardName == TimeZoneInfo.Local.StandardName && c.DaylightName == TimeZoneInfo.Local.DaylightName).FirstOrDefault(); } userProfile.TimeZone = currentTimeZone.Id; try { await _userService.UpdateUserProfileTimezoneWithErrorResponse(userProfile, "Time Zone Updated"); Console.WriteLine("<<<< Time Zone Updated! >>>>"); } catch (Exception ex) { Console.WriteLine("<<<< " + ex.Message + " >>>>"); } } } catch (Exception ex) { Console.WriteLine(ex.ToString()); } } async Task UpdateLanguage(Profile profile) { try { if (profile != null) { var currentLanguageIso = (await _cacheService.GetCurrentLanguage())?.Iso.ToLower(); if (profile?.Language?.Iso.ToLower() != currentLanguageIso) { await _cacheService.SaveCurrentLanguage(profile?.Language); await _languageService.GetTranslations(profile?.Language); } } } catch (Exception ex) { Console.WriteLine(ex.ToString()); } } /// /// Checks the message if password invalid. /// /// true, if message if password invalid was checked, false otherwise. /// Error message. private bool checkMessageIfPasswordInvalid(string errorMessage) { if (errorMessage.IndexOf("Please review your credentials", StringComparison.Ordinal) >= 0) { return true; } else if (errorMessage.IndexOf("You have one more attempt before your account is locked", StringComparison.Ordinal) >= 0) { return true; } return false; } /// /// Checks the message if account is locked. /// /// true, if message if account is locked was checked, false otherwise. /// Error message. private bool checkMessageIfAccountIsLocked(string errorMessage) { if (errorMessage.IndexOf("locked", StringComparison.Ordinal) >= 0) return true; return false; } /// /// Checks the message if account is disabled. /// /// true, if message if account is disabled was checked, false otherwise. /// Error message. private bool checkMessageIfAccountIsDisabled(string errorMessage) { if (errorMessage.IndexOf("disabled", StringComparison.Ordinal) >= 0) return true; return false; } /// /// Checks the message if user must reset password. /// /// true, if message if user must reset password was checked, false otherwise. /// Error message. private bool checkMessageIfUserMustResetPassword(string errorMessage) { if (errorMessage.IndexOf("Your password expired", StringComparison.Ordinal) >= 0) return true; if (errorMessage.IndexOf("expired", StringComparison.Ordinal) >= 0) return true; return false; } /// /// Checks the user been withdrawn from study. /// /// /// Error message. private bool checkMessageIfUserWithdrawnFromStudy(string errorMessage) { if (errorMessage.IndexOf("You have been withdrawn from the study", StringComparison.Ordinal) >= 0) return true; return false; } /// /// Updates the device. /// public static async void UpdateDevice() { try { //var pushDevicetoken = string.IsNullOrEmpty(Settings.GetProperty(Settings.PushDevicetoken)) ? String.Empty : Settings.GetProperty(Settings.PushDevicetoken); var pushDeviceToken = Preferences.Get("PushDeviceToken", string.Empty); var result = await UpdateDeviceTokenAsync(pushDeviceToken); Console.WriteLine("UpdateDevice result:>>" + result); } catch (Exception ex) { Console.WriteLine(ex); } } /// /// Updates the device token async. /// /// The device token async. /// Device token string. private static async Task UpdateDeviceTokenAsync(string deviceTokenString) { if (string.IsNullOrEmpty(deviceTokenString)) return null; string technologyString = null; //if (Device.RuntimePlatform == Device.Android) if (DeviceInfo.Platform == DevicePlatform.Android) { technologyString = "android"; } //else if (Device.RuntimePlatform == Device.iOS) else if (DeviceInfo.Platform == DevicePlatform.iOS) { technologyString = "ios"; } var service = new JsonApiHttpService { BaseUrl = EnvironmentConfig.ApiRoot, AuthToken = await new CacheService().GetAuthToken() }; var device = new Clinical6SDK.Helpers.Device { Id = await new CacheService().GetDeviceId(), MobileApplicationKey = EnvironmentConfig.MobileApplicationKey, Technology = technologyString, AppVersion = VersionTracking.CurrentVersion, PushId = deviceTokenString }; //Debug.WriteLine("device:>>" + device); //Debug.WriteLine($"device details:>> {System.Text.Json.JsonSerializer.Serialize(device, new JsonSerializerOptions { WriteIndented = true })}"); var result = await service.Update(device); //Debug.WriteLine("result:>>" + result); //Debug.WriteLine($"result:>> {System.Text.Json.JsonSerializer.Serialize(result, new JsonSerializerOptions { WriteIndented = true })}"); return result; } /// /// Ons the updatedterms complete. /// /// The updatedterms complete. protected async Task OnUpdatedtermsComplete() { _clinical6.User = await _mobileUserService.GetProfile(_clinical6.User); var dateTime = DateTime.UtcNow; _clinical6.User.PrivacyPolicyAcceptedAt = dateTime; _clinical6.User.TermsOfUseAcceptedAt = dateTime; _clinical6.User.AntiSpamPolicyAcceptedAt = dateTime; _clinical6.User.TimeZone = TimeZoneInfo.Local.StandardName; await _clinical6.User.Save(); await _userService.SaveTermsOfUseAccepted(true); } /// /// Gets the user profile. /// /// The user profile. private async Task GetUserProfile() { try { _clinical6.User = await _clinical6.GetProfile(); return _clinical6.User?.Profile; } catch (Exception exc) { Console.WriteLine($"GetUserProfile Exception: {exc}"); return null; } } /// /// /// /// private async Task ShowPoliciesAsync() { var Params = new AboutViewModel.InitValues(); Params.PolicyType = AboutViewModel.PolicyEnum.All; await Navigation.PushModal(Params); } public List _endpoints; public List Endpoints { get { return _endpoints; } set { _endpoints = value; OnPropertyChanged(nameof(Endpoints)); } } public string _selectedEndpoint; public string SelectedEndpoint { get { return _selectedEndpoint; } set { _selectedEndpoint = value; OnPropertyChanged(nameof(SelectedEndpoint)); ResetEndPointAsyn(); } } private async Task ResetEndPointAsyn() { var urlEndpoint = EnvironmentConfig.ApiRoot.Replace("-development", "-{0}") .Replace("-qa", "-{0}").Replace("-training", "-{0}") .Replace("-uat", "-{0}"); //We use the same aproch of VSS to sent the End Point await UpdateEndPointAsync(string.Format(urlEndpoint, SelectedEndpoint.ToLower())); await Navigation.StartLogin(); } private async Task UpdateEndPointAsync(string urlEndpoint) { Settings.SetProperty(Settings.ApiRoot, urlEndpoint); List settings = new List(); EnvironmentConfig.ApiRoot = urlEndpoint; ClientSingleton.Instance.BaseUrl = urlEndpoint; settings.Add(new AppSettings() { Id = nameof(ClientSingleton.Instance.BaseUrl), SettingsAttributes = new SettingsAttributes() { Value = ClientSingleton.Instance.BaseUrl } }); settings.Add(new AppSettings() { Id = nameof(EnvironmentConfig.MobileApplicationKey), SettingsAttributes = new SettingsAttributes() { Value = EnvironmentConfig.MobileApplicationKey } }); await _cacheService.SaveAPIStudySettings(settings); ClientSingleton.Instance.VerificationCodeUrl = urlEndpoint; } private async Task EndpointChangeTapped() { //If url is on production we cant change the url if (EnvironmentConfig.ApiRoot.IndexOf("development") > 0 || EnvironmentConfig.ApiRoot.IndexOf("qa") > 0 || EnvironmentConfig.ApiRoot.IndexOf("training") > 0 || EnvironmentConfig.ApiRoot.IndexOf("uat") > 0) { _endpoints = new List(); var urlEndpoint = EnvironmentConfig.ApiRoot.Replace("-development", string.Empty).Replace("-qa", string.Empty).Replace("-training", string.Empty).Replace("-uat", string.Empty); _endpoints.Add("Development"); _endpoints.Add("QA"); _endpoints.Add("Training"); _endpoints.Add("UAT"); OnPropertyChanged(nameof(Endpoints)); CallBackDisplayEndpoints?.Invoke(); } } private async Task SaveEmailToSecureStorage(string email) { try { await SecureStorage.SetAsync(Settings.NewSavedEmail, email); } catch (Exception exc) { Console.WriteLine($"Secure storage set exception: {exc}"); } } } }