1
0
mirror of https://github.com/bitwarden/mobile.git synced 2025-01-08 19:07:44 +01:00

Merge branch 'master' into PM-1575-display-passkeys

This commit is contained in:
Federico Maccaroni 2023-05-19 17:25:57 +03:00
commit 657dd3047c
No known key found for this signature in database
GPG Key ID: 5D233F8F2B034536
24 changed files with 527 additions and 196 deletions

View File

@ -38,6 +38,7 @@ namespace Bit.App
private readonly IFileService _fileService;
private readonly IAccountsManager _accountsManager;
private readonly IPushNotificationService _pushNotificationService;
private readonly IConfigService _configService;
private static bool _isResumed;
// these variables are static because the app is launching new activities on notification click, creating new instances of App.
private static bool _pendingCheckPasswordlessLoginRequests;
@ -61,6 +62,7 @@ namespace Bit.App
_fileService = ServiceContainer.Resolve<IFileService>();
_accountsManager = ServiceContainer.Resolve<IAccountsManager>("accountsManager");
_pushNotificationService = ServiceContainer.Resolve<IPushNotificationService>();
_configService = ServiceContainer.Resolve<IConfigService>();
_accountsManager.Init(() => Options, this);
@ -169,6 +171,10 @@ namespace Bit.App
new NavigationPage(new UpdateTempPasswordPage()));
});
}
else if (message.Command == "syncCompleted")
{
await _configService.GetAsync(true);
}
else if (message.Command == Constants.PasswordlessLoginRequestKey
|| message.Command == "unlocked"
|| message.Command == AccountsManagerMessageCommands.ACCOUNT_SWITCH_COMPLETED)
@ -293,6 +299,8 @@ namespace Bit.App
// Reset delay on every start
_vaultTimeoutService.DelayLockAndLogoutMs = null;
}
await _configService.GetAsync();
_messagingService.Send("startEventTimer");
}

View File

@ -3,6 +3,7 @@ using System.Threading.Tasks;
using System.Windows.Input;
using Bit.App.Resources;
using Bit.Core.Abstractions;
using Bit.Core.Models.Data;
using Bit.Core.Utilities;
using Xamarin.CommunityToolkit.ObjectModel;
@ -18,7 +19,8 @@ namespace Bit.App.Pages
_environmentService = ServiceContainer.Resolve<IEnvironmentService>("environmentService");
PageTitle = AppResources.Settings;
BaseUrl = _environmentService.BaseUrl;
BaseUrl = _environmentService.BaseUrl == EnvironmentUrlData.DefaultEU.Base || EnvironmentUrlData.DefaultUS.Base == _environmentService.BaseUrl ?
string.Empty : _environmentService.BaseUrl;
WebVaultUrl = _environmentService.WebVaultUrl;
ApiUrl = _environmentService.ApiUrl;
IdentityUrl = _environmentService.IdentityUrl;

View File

@ -25,10 +25,6 @@
AutomationProperties.IsInAccessibleTree="True"
AutomationProperties.Name="{u:I18n Account}" />
<ToolbarItem x:Name="_closeButton" Text="{u:I18n Close}" Command="{Binding CloseCommand}" Order="Primary" Priority="-1"/>
<ToolbarItem
Icon="cog_environment.png" Clicked="Environment_Clicked" Order="Primary"
AutomationProperties.IsInAccessibleTree="True"
AutomationProperties.Name="{u:I18n Options}" />
</ContentPage.ToolbarItems>
<ContentPage.Resources>
@ -66,7 +62,27 @@
</Entry>
<StackLayout
Orientation="Horizontal"
Margin="0, 16, 0 ,0">
Margin="0, 6, 0 ,0">
<StackLayout.GestureRecognizers>
<TapGestureRecognizer
Command="{Binding ShowEnvironmentPickerCommand}" />
</StackLayout.GestureRecognizers>
<Label
Text="{Binding RegionText}"
FontSize="13"
TextColor="{DynamicResource MutedColor}"
VerticalOptions="Center"
VerticalTextAlignment="Center"/>
<controls:IconLabel
Text="{Binding SelectedEnvironmentName}"
FontSize="13"
TextColor="{DynamicResource PrimaryColor}"
VerticalOptions="Center"
VerticalTextAlignment="Center"/>
</StackLayout>
<StackLayout
Orientation="Horizontal"
Margin="0, 20, 0 ,0">
<StackLayout.GestureRecognizers>
<TapGestureRecognizer
Command="{Binding RememberEmailCommand}" />

View File

@ -15,6 +15,8 @@ namespace Bit.App.Pages
private readonly AppOptions _appOptions;
private IBroadcasterService _broadcasterService;
readonly LazyResolve<ILogger> _logger = new LazyResolve<ILogger>();
public HomePage(AppOptions appOptions = null)
{
_broadcasterService = ServiceContainer.Resolve<IBroadcasterService>("broadcasterService");
@ -70,6 +72,14 @@ namespace Bit.App.Pages
});
}
});
try
{
await _vm.UpdateEnvironment();
}
catch (Exception ex)
{
_logger.Value?.Exception(ex);
}
}
protected override bool OnBackButtonPressed()
@ -128,14 +138,6 @@ namespace Bit.App.Pages
await Navigation.PushModalAsync(new NavigationPage(page));
}
private void Environment_Clicked(object sender, EventArgs e)
{
if (DoOnce())
{
_vm.StartEnvironmentAction();
}
}
private async Task StartEnvironmentAsync()
{
await _accountListOverlay.HideAsync();

View File

@ -4,7 +4,10 @@ using Bit.App.Abstractions;
using Bit.App.Controls;
using Bit.App.Resources;
using Bit.App.Utilities;
using Bit.Core;
using Bit.Core.Abstractions;
using Bit.Core.Models.Data;
using Bit.Core.Models.Response;
using Bit.Core.Services;
using Bit.Core.Utilities;
using Xamarin.CommunityToolkit.ObjectModel;
@ -17,16 +20,19 @@ namespace Bit.App.Pages
{
private readonly IStateService _stateService;
private readonly IMessagingService _messagingService;
private readonly IPlatformUtilsService _platformUtilsService;
private readonly ILogger _logger;
private readonly IEnvironmentService _environmentService;
private readonly IAccountsManager _accountManager;
private readonly IConfigService _configService;
private bool _showCancelButton;
private bool _rememberEmail;
private string _email;
private string _selectedEnvironmentName;
private bool _isEmailEnabled;
private bool _canLogin;
private IPlatformUtilsService _platformUtilsService;
private ILogger _logger;
private IEnvironmentService _environmentService;
private IAccountsManager _accountManager;
private bool _displayEuEnvironment;
public HomeViewModel()
{
@ -36,6 +42,7 @@ namespace Bit.App.Pages
_logger = ServiceContainer.Resolve<ILogger>();
_environmentService = ServiceContainer.Resolve<IEnvironmentService>();
_accountManager = ServiceContainer.Resolve<IAccountsManager>();
_configService = ServiceContainer.Resolve<IConfigService>();
PageTitle = AppResources.Bitwarden;
@ -49,6 +56,8 @@ namespace Bit.App.Pages
onException: _logger.Exception, allowsMultipleExecutions: false);
CloseCommand = new AsyncCommand(async () => await Device.InvokeOnMainThreadAsync(CloseAction),
onException: _logger.Exception, allowsMultipleExecutions: false);
ShowEnvironmentPickerCommand = new AsyncCommand(ShowEnvironmentPickerAsync,
onException: _logger.Exception, allowsMultipleExecutions: false);
InitAsync().FireAndForget();
}
@ -71,6 +80,13 @@ namespace Bit.App.Pages
additionalPropertyNames: new[] { nameof(CanContinue) });
}
public string SelectedEnvironmentName
{
get => $"{_selectedEnvironmentName} {BitwardenIcons.AngleDown}";
set => SetProperty(ref _selectedEnvironmentName, value);
}
public string RegionText => $"{AppResources.Region}:";
public bool CanContinue => !string.IsNullOrEmpty(Email);
public FormattedString CreateAccountText
@ -101,11 +117,13 @@ namespace Bit.App.Pages
public AsyncCommand ContinueCommand { get; }
public AsyncCommand CloseCommand { get; }
public AsyncCommand CreateAccountCommand { get; }
public AsyncCommand ShowEnvironmentPickerCommand { get; }
public async Task InitAsync()
{
Email = await _stateService.GetRememberedEmailAsync();
RememberEmail = !string.IsNullOrEmpty(Email);
_displayEuEnvironment = await _configService.GetFeatureFlagBoolAsync(Constants.DisplayEuEnvironmentFlag, forceRefresh: true);
}
public async Task ContinueToLoginStepAsync()
@ -144,5 +162,56 @@ namespace Bit.App.Pages
await _platformUtilsService.ShowDialogAsync(AppResources.GenericErrorMessage, AppResources.AnErrorHasOccurred, AppResources.Ok);
}
}
public async Task ShowEnvironmentPickerAsync()
{
var options = _displayEuEnvironment
? new string[] { AppResources.US, AppResources.EU, AppResources.SelfHosted }
: new string[] { AppResources.US, AppResources.SelfHosted };
await Device.InvokeOnMainThreadAsync(async () =>
{
var result = await Page.DisplayActionSheet(AppResources.DataRegion, AppResources.Cancel, null, options);
if (result is null || result == AppResources.Cancel)
{
return;
}
if (result == AppResources.SelfHosted)
{
StartEnvironmentAction?.Invoke();
return;
}
await _environmentService.SetUrlsAsync(result == AppResources.EU ? EnvironmentUrlData.DefaultEU : EnvironmentUrlData.DefaultUS);
SelectedEnvironmentName = result;
});
}
public async Task UpdateEnvironment()
{
var environmentsSaved = await _stateService.GetPreAuthEnvironmentUrlsAsync();
if (environmentsSaved == null || environmentsSaved.IsEmpty)
{
await _environmentService.SetUrlsAsync(EnvironmentUrlData.DefaultUS);
environmentsSaved = EnvironmentUrlData.DefaultUS;
SelectedEnvironmentName = AppResources.US;
return;
}
if (environmentsSaved.Base == EnvironmentUrlData.DefaultUS.Base)
{
SelectedEnvironmentName = AppResources.US;
}
else if (environmentsSaved.Base == EnvironmentUrlData.DefaultEU.Base)
{
SelectedEnvironmentName = AppResources.EU;
}
else
{
SelectedEnvironmentName = AppResources.SelfHosted;
}
}
}
}

View File

@ -41,6 +41,7 @@ namespace Bit.App.Pages
private bool _isEmailEnabled;
private bool _isKnownDevice;
private bool _isExecutingLogin;
private string _environmentHostName;
public LoginPageViewModel()
{
@ -115,6 +116,16 @@ namespace Bit.App.Pages
set => SetProperty(ref _isKnownDevice, value);
}
public string EnvironmentDomainName
{
get => _environmentHostName;
set => SetProperty(ref _environmentHostName, value,
additionalPropertyNames: new string[]
{
nameof(LoggingInAsText)
});
}
public AccountSwitchingOverlayViewModel AccountSwitchingOverlayViewModel { get; }
public Command LogInCommand { get; }
public Command TogglePasswordCommand { get; }
@ -122,7 +133,7 @@ namespace Bit.App.Pages
public ICommand LogInWithDeviceCommand { get; }
public string ShowPasswordIcon => ShowPassword ? BitwardenIcons.EyeSlash : BitwardenIcons.Eye;
public string PasswordVisibilityAccessibilityText => ShowPassword ? AppResources.PasswordIsVisibleTapToHide : AppResources.PasswordIsNotVisibleTapToShow;
public string LoggingInAsText => string.Format(AppResources.LoggingInAsX, Email);
public string LoggingInAsText => string.Format(AppResources.LoggingInAsXOnY, Email, EnvironmentDomainName);
public bool IsIosExtension { get; set; }
public bool CanRemoveAccount { get; set; }
public Action StartTwoFactorAction { get; set; }
@ -151,6 +162,7 @@ namespace Bit.App.Pages
Email = await _stateService.GetRememberedEmailAsync();
}
CanRemoveAccount = await _stateService.GetActiveUserEmailAsync() != Email;
EnvironmentDomainName = CoreHelpers.GetDomain((await _stateService.GetPreAuthEnvironmentUrlsAsync())?.Base);
IsKnownDevice = await _apiService.GetKnownDeviceAsync(Email, await _appIdService.GetAppIdAsync());
}
catch (ApiException apiEx) when (apiEx.Error.StatusCode == System.Net.HttpStatusCode.Unauthorized)

View File

@ -1768,6 +1768,15 @@ namespace Bit.App.Resources {
}
}
/// <summary>
/// Looks up a localized string similar to Data region.
/// </summary>
public static string DataRegion {
get {
return ResourceManager.GetString("DataRegion", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Password updated.
/// </summary>
@ -2344,6 +2353,15 @@ namespace Bit.App.Resources {
}
}
/// <summary>
/// Looks up a localized string similar to EU.
/// </summary>
public static string EU {
get {
return ResourceManager.GetString("EU", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Exact.
/// </summary>
@ -3587,11 +3605,11 @@ namespace Bit.App.Resources {
}
/// <summary>
/// Looks up a localized string similar to Logging in as {0}.
/// Looks up a localized string similar to Logging in as {0} on {1}.
/// </summary>
public static string LoggingInAsX {
public static string LoggingInAsXOnY {
get {
return ResourceManager.GetString("LoggingInAsX", resourceCulture);
return ResourceManager.GetString("LoggingInAsXOnY", resourceCulture);
}
}
@ -5174,6 +5192,15 @@ namespace Bit.App.Resources {
}
}
/// <summary>
/// Looks up a localized string similar to Region.
/// </summary>
public static string Region {
get {
return ResourceManager.GetString("Region", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Remember me.
/// </summary>
@ -5507,6 +5534,15 @@ namespace Bit.App.Resources {
}
}
/// <summary>
/// Looks up a localized string similar to Self-hosted.
/// </summary>
public static string SelfHosted {
get {
return ResourceManager.GetString("SelfHosted", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Self-hosted environment.
/// </summary>
@ -6578,6 +6614,15 @@ namespace Bit.App.Resources {
}
}
/// <summary>
/// Looks up a localized string similar to US.
/// </summary>
public static string US {
get {
return ResourceManager.GetString("US", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Use another two-step login method.
/// </summary>

View File

@ -346,7 +346,7 @@
<comment>Confirmation message after successfully deleting a login.</comment>
</data>
<data name="Submit" xml:space="preserve">
<value>Submit</value>
<value>জমা দিন</value>
</data>
<data name="Sync" xml:space="preserve">
<value>Sync</value>
@ -356,7 +356,7 @@
<value>ধন্যবাদ</value>
</data>
<data name="Tools" xml:space="preserve">
<value>Tools</value>
<value>টুলস</value>
<comment>The title for the tools page.</comment>
</data>
<data name="URI" xml:space="preserve">
@ -379,7 +379,7 @@
<comment>Confirmation message after successfully copying a value to the clipboard.</comment>
</data>
<data name="VerifyFingerprint" xml:space="preserve">
<value>Verify fingerprint</value>
<value>আঙ্গুলের ছাপ যাচাই করুন</value>
</data>
<data name="VerifyMasterPassword" xml:space="preserve">
<value>প্রধান পাসওয়ার্ড যাচাইকরণ</value>
@ -397,7 +397,7 @@
<value>আমাদের ওয়েবসাইটে ঢু মেরে আসুন</value>
</data>
<data name="VisitOurWebsiteDescription" xml:space="preserve">
<value>Visit our website to get help, news, email us, and/or learn more about how to use Bitwarden.</value>
<value>সাহায্য পেতে, খবর পেতে, আমাদের ইমেল করতে এবং/অথবা বিটওয়ার্ডেন কীভাবে ব্যবহার করবেন সে সম্পর্কে আরও জানতে আমাদের ওয়েবসাইট দেখুন।</value>
</data>
<data name="Website" xml:space="preserve">
<value>ওয়েবসাইট</value>
@ -413,7 +413,7 @@
<value>আপনার নতুন অ্যাকাউন্ট তৈরি করা হয়েছে! আপনি এখন লগইন করতে পারবেন।</value>
</data>
<data name="AddAnItem" xml:space="preserve">
<value>Add an Item</value>
<value>একটি আইটেম যোগ করুন</value>
</data>
<data name="AppExtension" xml:space="preserve">
<value>App extension</value>
@ -440,13 +440,13 @@
<value>Bitwarden Auto-fill Service</value>
</data>
<data name="BitwardenAutofillAccessibilityServiceDescription" xml:space="preserve">
<value>Use the Bitwarden accessibility service to auto-fill your logins.</value>
<value>আপনার লগইনগুলি স্বয়ংক্রিয়ভাবে পূরণ করতে বিটওয়ার্ডেন অ্যাক্সেসিবিলিটি পরিষেবা ব্যবহার করুন৷</value>
</data>
<data name="ChangeEmail" xml:space="preserve">
<value>ইমেইল পরিবর্তন করুন</value>
</data>
<data name="ChangeEmailConfirmation" xml:space="preserve">
<value>You can change your email address on the bitwarden.com web vault. Do you want to visit the website now?</value>
<value>আপনি bitwarden.com ওয়েব ভল্টে আপনার ইমেল ঠিকানা পরিবর্তন করতে পারেন। আপনি কি এখনই ওয়েবসাইট ভিজিট করতে চান?</value>
</data>
<data name="ChangeMasterPassword" xml:space="preserve">
<value>প্রধান পাসওয়ার্ড পরিবর্তন</value>
@ -511,7 +511,7 @@
<value>প্রিয়</value>
</data>
<data name="Fingerprint" xml:space="preserve">
<value>Fingerprint</value>
<value>আঙুলের ছাপ</value>
</data>
<data name="GeneratePassword" xml:space="preserve">
<value>পাসওয়ার্ড তৈরি করুন</value>
@ -584,7 +584,7 @@
<value>যদি আপনি আপনার পাসওয়ার্ড ভুলে যান তাহলে একটি প্রধান পাসওয়ার্ডের ইঙ্গিতটি আপনাকে মনে করাতে সাহায্য করতে পারে।</value>
</data>
<data name="MasterPasswordLengthValMessageX" xml:space="preserve">
<value>Master password must be at least {0} characters long.</value>
<value>মাস্টার পাসওয়ার্ড কমপক্ষে {0} অক্ষরের হতে হবে।</value>
</data>
<data name="MinNumbers" xml:space="preserve">
<value>সর্বনিম্ন সংখ্যা</value>
@ -595,7 +595,7 @@
<comment>Minimum special characters for password generator settings</comment>
</data>
<data name="MoreSettings" xml:space="preserve">
<value>More settings</value>
<value>আরও সেটিংস</value>
</data>
<data name="MustLogInMainApp" xml:space="preserve">
<value>You must log into the main Bitwarden app before you can use the extension.</value>
@ -684,7 +684,7 @@
<value>Item saved</value>
</data>
<data name="Submitting" xml:space="preserve">
<value>Submitting...</value>
<value>জমা দেওয়া হচ্ছে...</value>
<comment>Message shown when interacting with the server</comment>
</data>
<data name="Syncing" xml:space="preserve">
@ -717,7 +717,7 @@
<value>Unlock with PIN code</value>
</data>
<data name="Validating" xml:space="preserve">
<value>Validating</value>
<value>কার্যকর করা হচ্ছে</value>
<comment>Message shown when interacting with the server</comment>
</data>
<data name="VerificationCode" xml:space="preserve">
@ -876,7 +876,7 @@
<value>Unable to download file.</value>
</data>
<data name="UnableToOpenFile" xml:space="preserve">
<value>Your device cannot open this type of file.</value>
<value>আপনার ডিভাইস এই ধরনের ফাইল খুলতে পারে না।</value>
</data>
<data name="Downloading" xml:space="preserve">
<value>ডাউনলোড হচ্ছে...</value>

View File

@ -1753,10 +1753,10 @@
<comment>Confirmation alert message when soft-deleting a cipher.</comment>
</data>
<data name="AccountBiometricInvalidated" xml:space="preserve">
<value>Biometric unlock for this account is disabled pending verification of master password.</value>
<value>باز کردن قفل بیومتریک برای این حساب کاربری در انتظار تأیید کلمه عبور اصلی غیرفعال است.</value>
</data>
<data name="AccountBiometricInvalidatedExtension" xml:space="preserve">
<value>Autofill biometric unlock for this account is disabled pending verification of master password.</value>
<value>باز کردن قفل پر کردن خودکار بیومتریک برای این حساب کاربری در انتظار تأیید کلمه عبور اصلی غیرفعال است.</value>
</data>
<data name="EnableSyncOnRefresh" xml:space="preserve">
<value>فعال کردن همگام‌سازی در نوسازی</value>
@ -2144,10 +2144,10 @@
<value>سیاست‌های سازمانتان بر مهلت زمانی گاوصندوق شما تأثیر می‌گذارد. حداکثر زمان مجاز گاوصندوق {0} ساعت و {1} دقیقه است</value>
</data>
<data name="VaultTimeoutPolicyWithActionInEffect" xml:space="preserve">
<value>Your organization policies are affecting your vault timeout. Maximum allowed vault timeout is {0} hour(s) and {1} minute(s). Your vault timeout action is set to {2}.</value>
<value>سیاست‌های سازمانتان بر مهلت زمانی گاوصندوق شما تأثیر می‌گذارد. حداکثر زمان مجاز گاوصندوق {0} ساعت و {1} دقیقه است. عملگر مهلت زمانی گاوصندوق شما روی {2} تنظیم شده است.</value>
</data>
<data name="VaultTimeoutActionPolicyInEffect" xml:space="preserve">
<value>Your organization policies have set your vault timeout action to {0}.</value>
<value>سباست‌های سازمان شما، عملگر زمان‌بندی گاوصندوق شما را روی {0} تنظیم کرده است.</value>
</data>
<data name="VaultTimeoutToLarge" xml:space="preserve">
<value>مهلت زمانی شما بیش از محدودیت های تعیین شده توسط سازمانتان است.</value>
@ -2611,9 +2611,9 @@
<value>هیچ موردی وجود ندارد که با جستجو مطابقت داشته باشد</value>
</data>
<data name="UpdateWeakMasterPasswordWarning" xml:space="preserve">
<value>Your master password does not meet one or more of your organization policies. In order to access the vault, you must update your master password now. Proceeding will log you out of your current session, requiring you to log back in. Active sessions on other devices may continue to remain active for up to one hour.</value>
<value>کلمه عبور اصلی شما با یک یا چند سیاست سازمان‌تان مطابقت ندارد. برای دسترسی به گاوصندوق، باید همین حالا کلمه عبور اصلی خود را به‌روز کنید. در صورت ادامه، شما از نشست فعلی خود خارج می‌شوید و باید دوباره وارد سیستم شوید. نشست فعال در دستگاه های دیگر ممکن است تا یک ساعت همچنان فعال باقی بمانند.</value>
</data>
<data name="CurrentMasterPassword" xml:space="preserve">
<value>Current master password</value>
<value>کلمه عبور اصلی فعلی</value>
</data>
</root>

View File

@ -118,14 +118,14 @@
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="About" xml:space="preserve">
<value>बारे में</value>
<value>हमारे बारे में</value>
</data>
<data name="Add" xml:space="preserve">
<value>जोड़ें</value>
<comment>Add/create a new entity (verb).</comment>
</data>
<data name="AddFolder" xml:space="preserve">
<value>नया फोल्डर जोड़ें</value>
<value>फोल्डर जोड़ें</value>
</data>
<data name="AddItem" xml:space="preserve">
<value>चीज़ जोड़ें</value>
@ -136,11 +136,11 @@
<comment>Alert title when something goes wrong.</comment>
</data>
<data name="Back" xml:space="preserve">
<value>वापस जाएं</value>
<value>पीछे जाएं</value>
<comment>Navigate back to the previous screen.</comment>
</data>
<data name="Bitwarden" xml:space="preserve">
<value>bitwarden</value>
<value>बिटवार्डन</value>
<comment>App name. Shouldn't ever change.</comment>
</data>
<data name="Cancel" xml:space="preserve">
@ -156,105 +156,105 @@
<comment>The button text that allows a user to copy the login's password to their clipboard.</comment>
</data>
<data name="CopyUsername" xml:space="preserve">
<value>उपयोगकर्ता नाम की प्रतिलिपि बनाएँ</value>
<value>यूज़रनाम कॉपी करें</value>
<comment>The button text that allows a user to copy the login's username to their clipboard.</comment>
</data>
<data name="Credits" xml:space="preserve">
<value>क्रेडिट्स</value>
<value>क्रेडिट</value>
<comment>Title for page that we use to give credit to resources that we use.</comment>
</data>
<data name="Delete" xml:space="preserve">
<value>मिटाए</value>
<value>मिटाए</value>
<comment>Delete an entity (verb).</comment>
</data>
<data name="Deleting" xml:space="preserve">
<value>मिटाया जा रहा हैं</value>
<value>मिटाया जा रहा हैं...</value>
<comment>Message shown when interacting with the server</comment>
</data>
<data name="DoYouReallyWantToDelete" xml:space="preserve">
<value>क्या आप वास्तव में हटाना चाहते हैं? इसे नष्ट नहीं किया जा सकता है</value>
<value>पक्का मिटाएं? इसे अंडू नहीं किया जा सकता।</value>
<comment>Confirmation alert message when deleteing something.</comment>
</data>
<data name="Edit" xml:space="preserve">
<value>संशोधन करें</value>
<value>बदलाव करें</value>
</data>
<data name="EditFolder" xml:space="preserve">
<value>फ़ोल्डर संपादित करें</value>
<value>फोल्डर बदलाव करें</value>
</data>
<data name="Email" xml:space="preserve">
<value>ईमेल</value>
<comment>Short label for an email address.</comment>
</data>
<data name="EmailAddress" xml:space="preserve">
<value>ई-मेल पता</value>
<value>ईमेल पता</value>
<comment>Full label for a email address.</comment>
</data>
<data name="EmailUs" xml:space="preserve">
<value>हमें ईमेल करें</value>
</data>
<data name="EmailUsDescription" xml:space="preserve">
<value>सहायता प्राप्त करने या प्रतिक्रिया छोड़ने के लिए हमें ईमेल करें।</value>
<value>मदद लेने या फीडबैक देने के लिए हमें ईमेल करें।</value>
</data>
<data name="EnterPIN" xml:space="preserve">
<value>अपना पिन डालें</value>
<value>अपना पिन कोड डालें</value>
</data>
<data name="Favorites" xml:space="preserve">
<value>पसंदीदा</value>
<value>मनपसंद</value>
<comment>Title for your favorite items in the vault.</comment>
</data>
<data name="FileBugReport" xml:space="preserve">
<value>बग रिपोर्ट दर्ज करें</value>
<value>बग रिपोर्ट भेजें</value>
</data>
<data name="FileBugReportDescription" xml:space="preserve">
<value>हमारे GitHub भंडार में एक मुद्दे को बताएं।</value>
<value>हमारे गिटहब रिपॉज़िटरी में समस्या बताएं।</value>
</data>
<data name="FingerprintDirection" xml:space="preserve">
<value>फिंगरप्रिंट से सत्यापन करें</value>
<value>फिंगरप्रिंट से सत्यापन करें</value>
</data>
<data name="Folder" xml:space="preserve">
<value>फोल्डर</value>
<value>फोल्डर</value>
<comment>Label for a folder.</comment>
</data>
<data name="FolderCreated" xml:space="preserve">
<value>नया फोल्डर बनाया गया</value>
<value>नया फोल्डर बनाया गया</value>
</data>
<data name="FolderDeleted" xml:space="preserve">
<value>फ़ोल्डर को हटाया</value>
<value>फोल्डर मिटाया गया।</value>
</data>
<data name="FolderNone" xml:space="preserve">
<value>कोई फोल्डर नहीं है</value>
<value>कोई फोल्डर नहीं है</value>
<comment>Items that have no folder specified go in this special "catch-all" folder.</comment>
</data>
<data name="Folders" xml:space="preserve">
<value>फोल्डर्स</value>
<value>फोल्डर</value>
</data>
<data name="FolderUpdated" xml:space="preserve">
<value>फ़ोल्डर अद्यतन हुआ</value>
<value>फोल्डर सेव हुआ</value>
</data>
<data name="GoToWebsite" xml:space="preserve">
<value>वेबसाइट पर जाए</value>
<value>वेबसाइट पर जाए</value>
<comment>The button text that allows user to launch the website to their web browser.</comment>
</data>
<data name="HelpAndFeedback" xml:space="preserve">
<value>सहायता और सुझाव</value>
<value>मदद और फीडबैक</value>
</data>
<data name="Hide" xml:space="preserve">
<value>छुपायें</value>
<value>छुपां</value>
<comment>Hide a secret value that is currently shown (password).</comment>
</data>
<data name="InternetConnectionRequiredMessage" xml:space="preserve">
<value>जारी रखने से पहले कृपया इंटरनेट से जुड़े।</value>
<value>जारी रखने से पहले इंटरनेट से जुड़े।</value>
<comment>Description message for the alert when internet connection is required to continue.</comment>
</data>
<data name="InternetConnectionRequiredTitle" xml:space="preserve">
<value>इंटरनेट से जुड़िए।</value>
<value>इंटरनेट कनेक्शन चाहिए</value>
<comment>Title for the alert when internet connection is required to continue.</comment>
</data>
<data name="InvalidMasterPassword" xml:space="preserve">
<value>मास्टर पासवर्ड गलत है। फिर कोशिश करें।</value>
<value>मुख्य पासवर्ड गलत है। वापस कोशिश करें।</value>
</data>
<data name="InvalidPIN" xml:space="preserve">
<value>पिन गलत है। फिर कोशिश करें।</value>
<value>पिन गलत है। वापस कोशिश करें।</value>
</data>
<data name="Launch" xml:space="preserve">
<value>खोलें</value>
@ -269,38 +269,38 @@
<comment>Title for login page. (noun)</comment>
</data>
<data name="LogOut" xml:space="preserve">
<value>लॉग आउट</value>
<value>लॉग आउट करें</value>
<comment>The log out button text (verb).</comment>
</data>
<data name="LogoutConfirmation" xml:space="preserve">
<value>क्या आप वाकई लॉग आउट करना चाहते हैं?</value>
<value>पक्का लॉग आउट करें?</value>
</data>
<data name="RemoveAccount" xml:space="preserve">
<value>खाता हटाएं</value>
</data>
<data name="RemoveAccountConfirmation" xml:space="preserve">
<value>क्या आप वाकई यह खाता हटाना चाहते हैं?</value>
<value>पक्का खाता हटाएं?</value>
</data>
<data name="AccountAlreadyAdded" xml:space="preserve">
<value>Account already added</value>
<value>खाता पहले से जोड़ा गया</value>
</data>
<data name="SwitchToAlreadyAddedAccountConfirmation" xml:space="preserve">
<value>Would you like to switch to it now?</value>
<value>अभी खाता इस्तेमाल करें?</value>
</data>
<data name="MasterPassword" xml:space="preserve">
<value>मास्टर / मुख्य पासवर्ड</value>
<value>मुख्य पासवर्ड</value>
<comment>Label for a master password.</comment>
</data>
<data name="More" xml:space="preserve">
<value>अतिरिक्त</value>
<value>और</value>
<comment>Text to define that there are more options things to see.</comment>
</data>
<data name="MyVault" xml:space="preserve">
<value>मेर तिजोरी</value>
<value>मेर तिजोरी</value>
<comment>The title for the vault page.</comment>
</data>
<data name="Authenticator" xml:space="preserve">
<value>Authenticator</value>
<value>सत्यापन करनेवाला</value>
<comment>Authenticator TOTP feature</comment>
</data>
<data name="Name" xml:space="preserve">
@ -311,11 +311,11 @@
<value>नहीं</value>
</data>
<data name="Notes" xml:space="preserve">
<value>टिप्पणियाँ</value>
<value>नोट</value>
<comment>Label for notes.</comment>
</data>
<data name="Ok" xml:space="preserve">
<value>ठीक</value>
<value>ठीक है</value>
<comment>Acknowledgement.</comment>
</data>
<data name="Password" xml:space="preserve">
@ -323,69 +323,69 @@
<comment>Label for a password.</comment>
</data>
<data name="Save" xml:space="preserve">
<value>सहेजें</value>
<value>सेव करें</value>
<comment>Button text for a save operation (verb).</comment>
</data>
<data name="Move" xml:space="preserve">
<value>Move</value>
<value>ले जाएं</value>
</data>
<data name="Saving" xml:space="preserve">
<value>सेव हो रहा है...</value>
<comment>Message shown when interacting with the server</comment>
</data>
<data name="Settings" xml:space="preserve">
<value>सेटिंग्स</value>
<value>सेटिंग</value>
<comment>The title for the settings page.</comment>
</data>
<data name="Show" xml:space="preserve">
<value>दिखाए</value>
<value>दिखाए</value>
<comment>Reveal a hidden value (password).</comment>
</data>
<data name="ItemDeleted" xml:space="preserve">
<value>आइटम हटा दिया गया है।</value>
<value>चीज़ मिटाया गया।</value>
<comment>Confirmation message after successfully deleting a login.</comment>
</data>
<data name="Submit" xml:space="preserve">
<value>जमा करें</value>
</data>
<data name="Sync" xml:space="preserve">
<value>संकालन</value>
<value>सिंक</value>
<comment>The title for the sync page.</comment>
</data>
<data name="ThankYou" xml:space="preserve">
<value>धन्यवाद</value>
<value>शुक्रिया</value>
</data>
<data name="Tools" xml:space="preserve">
<value>उपकरण</value>
<value>औज़ार</value>
<comment>The title for the tools page.</comment>
</data>
<data name="URI" xml:space="preserve">
<value>URI</value>
<value>यूआरआई</value>
<comment>Label for a uri/url.</comment>
</data>
<data name="UseFingerprintToUnlock" xml:space="preserve">
<value>अंगुलिछाप से खोलें</value>
<value>फिंगरप्रिंट से खोलें</value>
</data>
<data name="Username" xml:space="preserve">
<value>उपयोगकर्ता नाम:</value>
<value>यूज़रनाम</value>
<comment>Label for a username.</comment>
</data>
<data name="ValidationFieldRequired" xml:space="preserve">
<value>{0} की आश्यकता है।</value>
<value>{0} फील्ड चाहिए।</value>
<comment>Validation message for when a form field is left blank and is required to be entered.</comment>
</data>
<data name="ValueHasBeenCopied" xml:space="preserve">
<value>{0} कॉपी कर लिया गया है।</value>
<value>{0} कॉपी किया</value>
<comment>Confirmation message after successfully copying a value to the clipboard.</comment>
</data>
<data name="VerifyFingerprint" xml:space="preserve">
<value>अंगुलिछाप दें</value>
<value>फिंगरप्रिंट सत्यापित करें</value>
</data>
<data name="VerifyMasterPassword" xml:space="preserve">
<value>मास्टर पासवर्ड बताएं।</value>
<value>मुख्य पासवर्ड सत्यापित करें</value>
</data>
<data name="VerifyPIN" xml:space="preserve">
<value>पिन बताएं।</value>
<value>पिन सत्यापित करें।</value>
</data>
<data name="Version" xml:space="preserve">
<value>संस्करण</value>
@ -394,29 +394,29 @@
<value>देखें</value>
</data>
<data name="VisitOurWebsite" xml:space="preserve">
<value>हमारी वेबसाइट पर जाए</value>
<value>हमारी वेबसाइट पर जाए</value>
</data>
<data name="VisitOurWebsiteDescription" xml:space="preserve">
<value>Visit our website to get help, news, email us, and/or learn more about how to use bitwarden.</value>
<value>मदद लेने, खबर लेने, हमें ईमेल करने, और/या बिटवार्डन के इस्तेमाल के बारे में ज़्यादा जानने के लिए हमारी वेबसाइट पर जाएं।</value>
</data>
<data name="Website" xml:space="preserve">
<value>वेबसाइट</value>
<comment>Label for a website.</comment>
</data>
<data name="Yes" xml:space="preserve">
<value>हा</value>
<value>हा</value>
</data>
<data name="Account" xml:space="preserve">
<value>खाता</value>
</data>
<data name="AccountCreated" xml:space="preserve">
<value>अपना नया खाता बनाया गया है! अब आप लॉग ऑन कर सकते हैं।</value>
<value>आपका नया खाता बनाया गया! अब आप लॉग इन कर सकते हैं।</value>
</data>
<data name="AddAnItem" xml:space="preserve">
<value>आइटम जोड़ें</value>
<value>चीज़ जोड़ें</value>
</data>
<data name="AppExtension" xml:space="preserve">
<value>ऐप का विस्तारण</value>
<value>ऐप एक्सटेंशन</value>
</data>
<data name="AutofillAccessibilityDescription" xml:space="preserve">
<value>Use the bitwarden accessibility service to auto-fill your logins across apps and the web.</value>
@ -776,10 +776,10 @@
<value>सक्षम</value>
</data>
<data name="Off" xml:space="preserve">
<value>Off</value>
<value>बंद</value>
</data>
<data name="On" xml:space="preserve">
<value>On</value>
<value>चालू</value>
</data>
<data name="Status" xml:space="preserve">
<value>स्थिति</value>
@ -1096,16 +1096,16 @@ Scanning will happen automatically.</value>
<value>मध्य नाम</value>
</data>
<data name="Mr" xml:space="preserve">
<value>Mr</value>
<value>श्री</value>
</data>
<data name="Mrs" xml:space="preserve">
<value>Mrs</value>
<value>श्रीमती</value>
</data>
<data name="Ms" xml:space="preserve">
<value>Ms</value>
<value>श्रीमती</value>
</data>
<data name="Mx" xml:space="preserve">
<value>Mx</value>
<value>मैक्स</value>
</data>
<data name="November" xml:space="preserve">
<value>नवंबर</value>
@ -2274,7 +2274,7 @@ Scanning will happen automatically.</value>
<value>Vault: {0}</value>
</data>
<data name="All" xml:space="preserve">
<value>All</value>
<value>सब</value>
</data>
<data name="Totp" xml:space="preserve">
<value>TOTP</value>
@ -2365,13 +2365,13 @@ select Add TOTP to store the key safely</value>
<value>Login denied</value>
</data>
<data name="ApproveLoginRequests" xml:space="preserve">
<value>Approve login requests</value>
<value>लॉगइन मांग माने</value>
</data>
<data name="UseThisDeviceToApproveLoginRequestsMadeFromOtherDevices" xml:space="preserve">
<value>Use this device to approve login requests made from other devices.</value>
</data>
<data name="AllowNotifications" xml:space="preserve">
<value>Allow notifications</value>
<value>सूचना देने दें</value>
</data>
<data name="ReceivePushNotificationsForNewLoginRequests" xml:space="preserve">
<value>Receive push notifications for new login requests</value>
@ -2522,99 +2522,99 @@ Do you want to switch to this account?</value>
<value>Resend notification</value>
</data>
<data name="NeedAnotherOption" xml:space="preserve">
<value>Need another option?</value>
<value>दूसरा ऑप्शन चाहिए?</value>
</data>
<data name="ViewAllLoginOptions" xml:space="preserve">
<value>View all log in options</value>
<value>ऑप्शन में सारे लॉग देखें</value>
</data>
<data name="ThisRequestIsNoLongerValid" xml:space="preserve">
<value>This request is no longer valid</value>
<value>ये मांग अब मान्य नहीं है</value>
</data>
<data name="PendingLogInRequests" xml:space="preserve">
<value>Pending login requests</value>
<value>लंबित लॉगइन मांगे</value>
</data>
<data name="DeclineAllRequests" xml:space="preserve">
<value>Decline all requests</value>
<value>सारे मांग नकारे</value>
</data>
<data name="AreYouSureYouWantToDeclineAllPendingLogInRequests" xml:space="preserve">
<value>Are you sure you want to decline all pending login requests?</value>
<value>सारे लंबित लॉगइन मांग पक्का नकारें?</value>
</data>
<data name="RequestsDeclined" xml:space="preserve">
<value>Requests declined</value>
<value>मांग नकारे गए</value>
</data>
<data name="NoPendingRequests" xml:space="preserve">
<value>No pending requests</value>
<value>कोई लंबित मांग नहीं</value>
</data>
<data name="EnableCamerPermissionToUseTheScanner" xml:space="preserve">
<value>Enable camera permission to use the scanner</value>
<value>स्कैनर इस्तेमाल करने के लिए कैमरा अनुमति दें</value>
</data>
<data name="Language" xml:space="preserve">
<value>Language</value>
<value>भाषा</value>
</data>
<data name="LanguageChangeXDescription" xml:space="preserve">
<value>The language has been changed to {0}. Please restart the app to see the change</value>
<value>भाषा {0} में बदली गई। बदलाव देखने के लिए ऐप बंद करके वापस खोलें।</value>
</data>
<data name="LanguageChangeRequiresAppRestart" xml:space="preserve">
<value>Language change requires app restart</value>
<value>भाषा बदलाव के लिए ऐप बंद करके खोलना पड़ेगा</value>
</data>
<data name="DefaultSystem" xml:space="preserve">
<value>Default (System)</value>
<value>डिफॉल्ट (सिस्टम)</value>
</data>
<data name="Important" xml:space="preserve">
<value>Important</value>
<value>ज़रूरी</value>
</data>
<data name="YourMasterPasswordCannotBeRecoveredIfYouForgetItXCharactersMinimum" xml:space="preserve">
<value>Your master password cannot be recovered if you forget it! {0} characters minimum.</value>
<value>आप अपना मुख्य पासवर्ड भूलने के बाद वापस नहीं ले सकते। {0} अक्षर कम-से-कम।</value>
</data>
<data name="WeakMasterPassword" xml:space="preserve">
<value>Weak Master Password</value>
<value>कमज़ोर मुख्य पासवर्ड</value>
</data>
<data name="WeakPasswordIdentifiedUseAStrongPasswordToProtectYourAccount" xml:space="preserve">
<value>Weak password identified. Use a strong password to protect your account. Are you sure you want to use a weak password?</value>
<value>पासवर्ड कमज़ोर है। अपना खाता महफूज़ रखने के लिए एक ताकतवर पासवर्ड इस्तेमाल करें। कमज़ोर पासवर्ड पक्का इस्तेमाल करें?</value>
</data>
<data name="Weak" xml:space="preserve">
<value>Weak</value>
<value>कमज़ोर</value>
</data>
<data name="Good" xml:space="preserve">
<value>Good</value>
<value>अच्छा</value>
</data>
<data name="Strong" xml:space="preserve">
<value>Strong</value>
<value>ताकतवर</value>
</data>
<data name="CheckKnownDataBreachesForThisPassword" xml:space="preserve">
<value>Check known data breaches for this password</value>
<value>पुराने डाटा लीक में इस पासवर्ड को खोजें</value>
</data>
<data name="ExposedMasterPassword" xml:space="preserve">
<value>Exposed Master Password</value>
<value>मुख्य पासवर्ड लीक हुआ था</value>
</data>
<data name="PasswordFoundInADataBreachAlertDescription" xml:space="preserve">
<value>Password found in a data breach. Use a unique password to protect your account. Are you sure you want to use an exposed password?</value>
<value>पासवर्ड एक डाटा लीक में मिला। अपना खाता महफूज़ रखने के लिए एक खास पासवर्ड इस्तेमाल करें। लीक हुआ पासवर्ड इस्तेमाल करें?</value>
</data>
<data name="WeakAndExposedMasterPassword" xml:space="preserve">
<value>Weak and Exposed Master Password</value>
<value>कमज़ोर और लीक हुआ मुख्य पासवर्ड</value>
</data>
<data name="WeakPasswordIdentifiedAndFoundInADataBreachAlertDescription" xml:space="preserve">
<value>Weak password identified and found in a data breach. Use a strong and unique password to protect your account. Are you sure you want to use this password?</value>
<value>पासवर्ड कमज़ोर है और एक डाटा लीक में मिला। अपना खाता महफूज़ रखने के लिए एक ताकतवर और खास पासवर्ड इस्तेमाल करें। ये पासवर्ड पक्का इस्तेमाल करें?</value>
</data>
<data name="OrganizationSsoIdentifierRequired" xml:space="preserve">
<value>Organization SSO identifier required.</value>
<value>संगठन एसएसओ पहचान चाहिए।</value>
</data>
<data name="AddTheKeyToAnExistingOrNewItem" xml:space="preserve">
<value>Add the key to an existing or new item</value>
<value>चाबी एक मौजूदा या नए चीज़ में जोड़ें</value>
</data>
<data name="ThereAreNoItemsInYourVaultThatMatchX" xml:space="preserve">
<value>There are no items in your vault that match "{0}"</value>
<value>आपके तिजोरी में ऐसी कोई भी चीज़ नहीं है जो "{0}" से मेल खाती है</value>
</data>
<data name="SearchForAnItemOrAddANewItem" xml:space="preserve">
<value>Search for an item or add a new item</value>
<value>चीज़ खोजें या नया चीज़ जोड़ें</value>
</data>
<data name="ThereAreNoItemsThatMatchTheSearch" xml:space="preserve">
<value>There are no items that match the search</value>
<value>कोई भी चीज़ खोज शब्द से मेल नहीं खाता</value>
</data>
<data name="UpdateWeakMasterPasswordWarning" xml:space="preserve">
<value>Your master password does not meet one or more of your organization policies. In order to access the vault, you must update your master password now. Proceeding will log you out of your current session, requiring you to log back in. Active sessions on other devices may continue to remain active for up to one hour.</value>
<value>आपका मुख्य पासवर्ड आपके संगठन के एक या उससे ज़्यादा नीति को नहीं मानता। तिजोरी एक्सेस करने के लिए आपको अपना मुख्य पासवर्ड अभी बदलना होगा। ये करने से आप अपने चालू सत्र से लॉग आउट हो जाएंगे, जिसके वजह से आपको वापस लॉग इन करना पड़ेगा। दूसरे डिवाइसों पर चालू सत्र एक घंटे तक सक्रिय रह सकते हैं।</value>
</data>
<data name="CurrentMasterPassword" xml:space="preserve">
<value>Current master password</value>
<value>चालू मुख्य पासवर्ड</value>
</data>
</root>

View File

@ -2496,8 +2496,8 @@ Do you want to switch to this account?</value>
<data name="GetMasterPasswordwordHint" xml:space="preserve">
<value>Get master password hint</value>
</data>
<data name="LoggingInAsX" xml:space="preserve">
<value>Logging in as {0}</value>
<data name="LoggingInAsXOnY" xml:space="preserve">
<value>Logging in as {0} on {1}</value>
</data>
<data name="NotYou" xml:space="preserve">
<value>Not you?</value>
@ -2610,6 +2610,21 @@ Do you want to switch to this account?</value>
<data name="ThereAreNoItemsThatMatchTheSearch" xml:space="preserve">
<value>There are no items that match the search</value>
</data>
<data name="US" xml:space="preserve">
<value>US</value>
</data>
<data name="EU" xml:space="preserve">
<value>EU</value>
</data>
<data name="SelfHosted" xml:space="preserve">
<value>Self-hosted</value>
</data>
<data name="DataRegion" xml:space="preserve">
<value>Data region</value>
</data>
<data name="Region" xml:space="preserve">
<value>Region</value>
</data>
<data name="UpdateWeakMasterPasswordWarning" xml:space="preserve">
<value>Your master password does not meet one or more of your organization policies. In order to access the vault, you must update your master password now. Proceeding will log you out of your current session, requiring you to log back in. Active sessions on other devices may continue to remain active for up to one hour.</value>
</data>

View File

@ -1753,10 +1753,10 @@
<comment>Confirmation alert message when soft-deleting a cipher.</comment>
</data>
<data name="AccountBiometricInvalidated" xml:space="preserve">
<value>Biometric unlock for this account is disabled pending verification of master password.</value>
<value>Біометричне розблокування для цього облікового запису вимкнено. Очікується перевірка головного пароля.</value>
</data>
<data name="AccountBiometricInvalidatedExtension" xml:space="preserve">
<value>Autofill biometric unlock for this account is disabled pending verification of master password.</value>
<value>Біометричне розблокування під час автозаповнення для цього облікового запису вимкнено. Очікується перевірка головного пароля.</value>
</data>
<data name="EnableSyncOnRefresh" xml:space="preserve">
<value>Дозволити синхронізацію жестом</value>

View File

@ -92,5 +92,6 @@ namespace Bit.Core.Abstractions
Task<string> GetUsernameFromAsync(ForwardedEmailServiceType service, UsernameGeneratorConfig config);
Task<bool> GetKnownDeviceAsync(string email, string deviceIdentifier);
Task<OrganizationDomainSsoDetailsResponse> GetOrgDomainSsoDetailsAsync(string email);
Task<ConfigResponse> GetConfigsAsync();
}
}

View File

@ -0,0 +1,15 @@
using System;
using System.Threading.Tasks;
using Bit.Core.Models.Response;
namespace Bit.Core.Abstractions
{
public interface IConfigService
{
Task<ConfigResponse> GetAsync(bool forceRefresh = false);
Task<bool> GetFeatureFlagBoolAsync(string key, bool forceRefresh = false, bool defaultValue = false);
Task<string> GetFeatureFlagStringAsync(string key, bool forceRefresh = false, string defaultValue = null);
Task<int> GetFeatureFlagIntAsync(string key, bool forceRefresh = false, int defaultValue = 0);
}
}

View File

@ -174,5 +174,7 @@ namespace Bit.Core.Abstractions
Task SetPreLoginEmailAsync(string value);
string GetLocale();
void SetLocale(string locale);
ConfigResponse GetConfigs();
void SetConfigs(ConfigResponse value);
}
}

View File

@ -41,6 +41,9 @@
public const string NotificationDataType = "Type";
public const string PasswordlessLoginRequestKey = "passwordlessLoginRequest";
public const string PreLoginEmailKey = "preLoginEmailKey";
public const string ConfigsKey = "configsKey";
public const string DisplayEuEnvironmentFlag = "display-eu-environment";
/// <summary>
/// This key is used to store the value of "ShouldConnectToWatch" of the last user that had logged in
/// which is used to handle Apple Watch state logic

View File

@ -2,6 +2,9 @@
{
public class EnvironmentUrlData
{
public static EnvironmentUrlData DefaultUS = new EnvironmentUrlData { Base = "https://vault.bitwarden.com" };
public static EnvironmentUrlData DefaultEU = new EnvironmentUrlData { Base = "https://vault.bitwarden.eu" };
public string Base { get; set; }
public string Api { get; set; }
public string Identity { get; set; }
@ -9,5 +12,13 @@
public string Notifications { get; set; }
public string WebVault { get; set; }
public string Events { get; set; }
public bool IsEmpty => string.IsNullOrEmpty(Base)
&& string.IsNullOrEmpty(Api)
&& string.IsNullOrEmpty(Identity)
&& string.IsNullOrEmpty(Icons)
&& string.IsNullOrEmpty(Notifications)
&& string.IsNullOrEmpty(WebVault)
&& string.IsNullOrEmpty(Events);
}
}

View File

@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
namespace Bit.Core.Models.Response
{
public class ConfigResponse
{
public string Version { get; set; }
public string GitHash { get; set; }
public ServerConfigResponse Server { get; set; }
public EnvironmentConfigResponse Environment { get; set; }
public IDictionary<string, object> FeatureStates { get; set; }
public DateTime ExpiresOn { get; set; }
}
public class ServerConfigResponse
{
public string Name { get; set; }
public string Url { get; set; }
}
public class EnvironmentConfigResponse
{
public string Vault { get; set; }
public string Api { get; set; }
public string Identity { get; set; }
public string Notifications { get; set; }
public string Sso { get; set; }
}
}

View File

@ -585,6 +585,16 @@ namespace Bit.Core.Services
#endregion
#region Configs
public async Task<ConfigResponse> GetConfigsAsync()
{
var accessToken = await _tokenService.GetTokenAsync();
return await SendAsync<object, ConfigResponse>(HttpMethod.Get, "/config/", null, !string.IsNullOrEmpty(accessToken), true);
}
#endregion
#region Helpers
public async Task<string> GetActiveBearerTokenAsync()

View File

@ -0,0 +1,77 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Bit.Core.Abstractions;
using Bit.Core.Exceptions;
using Bit.Core.Models.Domain;
using Bit.Core.Models.Response;
using Bit.Core.Models.View;
namespace Bit.Core.Services
{
public class ConfigService : IConfigService
{
private const int UPDATE_INTERVAL_MINS = 60;
private ConfigResponse _configs;
private readonly IApiService _apiService;
private readonly IStateService _stateService;
private readonly ILogger _logger;
public ConfigService(IApiService apiService, IStateService stateService, ILogger logger)
{
_apiService = apiService;
_stateService = stateService;
_logger = logger;
}
public async Task<ConfigResponse> GetAsync(bool forceRefresh = false)
{
try
{
_configs = _stateService.GetConfigs();
if (forceRefresh || _configs?.ExpiresOn is null || _configs.ExpiresOn <= DateTime.UtcNow)
{
_configs = await _apiService.GetConfigsAsync();
_configs.ExpiresOn = DateTime.UtcNow.AddMinutes(UPDATE_INTERVAL_MINS);
_stateService.SetConfigs(_configs);
}
}
catch (ApiException ex) when (ex.Error.StatusCode == System.Net.HttpStatusCode.BadGateway)
{
// ignore if there is no internet connection and return local configs
}
catch (Exception ex)
{
_logger.Exception(ex);
}
return _configs;
}
public async Task<bool> GetFeatureFlagBoolAsync(string key, bool forceRefresh = false, bool defaultValue = false) => await GetFeatureFlagAsync<bool>(key, forceRefresh, defaultValue);
public async Task<string> GetFeatureFlagStringAsync(string key, bool forceRefresh = false, string defaultValue = null) => await GetFeatureFlagAsync<string>(key, forceRefresh, defaultValue);
public async Task<int> GetFeatureFlagIntAsync(string key, bool forceRefresh = false, int defaultValue = 0) => await GetFeatureFlagAsync<int>(key, forceRefresh, defaultValue);
private async Task<T> GetFeatureFlagAsync<T>(string key, bool forceRefresh = false, T defaultValue = default)
{
await GetAsync(forceRefresh);
if (_configs == null || _configs.FeatureStates == null)
{
return defaultValue;
}
if (_configs.FeatureStates.TryGetValue(key, out var val) == true
&&
val is T actualValue)
{
return actualValue;
}
return defaultValue;
}
}
}

View File

@ -1280,6 +1280,16 @@ namespace Bit.Core.Services
await SetValueAsync(Constants.PreLoginEmailKey, value, options);
}
public ConfigResponse GetConfigs()
{
return _storageMediatorService.Get<ConfigResponse>(Constants.ConfigsKey);
}
public void SetConfigs(ConfigResponse value)
{
_storageMediatorService.Save(Constants.ConfigsKey, value);
}
// Helpers
[Obsolete("Use IStorageMediatorService instead")]

View File

@ -87,6 +87,7 @@ namespace Bit.Core.Utilities
var userVerificationService = new UserVerificationService(apiService, platformUtilsService, i18nService,
cryptoService);
var usernameGenerationService = new UsernameGenerationService(cryptoService, apiService, stateService);
var configService = new ConfigService(apiService, stateService, logger);
Register<IConditionedAwaiterManager>(conditionedRunner);
Register<ITokenService>("tokenService", tokenService);
@ -112,6 +113,7 @@ namespace Bit.Core.Utilities
Register<IKeyConnectorService>("keyConnectorService", keyConnectorService);
Register<IUserVerificationService>("userVerificationService", userVerificationService);
Register<IUsernameGenerationService>(usernameGenerationService);
Register<IConfigService>(configService);
}
public static void Register<T>(string serviceName, T obj)

View File

@ -118,55 +118,55 @@
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Name" xml:space="preserve">
<value>Bitwarden पासवर्ड मैनेजर</value>
<value>बिटवार्डन पासवर्ड मैनेजर</value>
<comment>Max 30 characters</comment>
</data>
<data name="Description" xml:space="preserve">
<value>Bitwarden, Inc. is the parent company of 8bit Solutions LLC.
<value>बिटवार्डन अंतरराष्ट्रीय कॉरपोरेशन, 8बिट सॉल्यूश्नस एलएलसी की मूल कंपनी है।
NAMED BEST PASSWORD MANAGER BY THE VERGE, U.S. NEWS &amp; WORLD REPORT, CNET, AND MORE.
द वर्ज, यूएस न्यूज़ एंड वर्ल्ड रिपोर्ट, सीनेट, और कई दूसरे मीडिया संगठन द्वारा बोला गया दुनिया का सबसे बेहतरीन पासवर्ड मैनेजर।
Manage, store, secure, and share unlimited passwords across unlimited devices from anywhere. Bitwarden delivers open source password management solutions to everyone, whether at home, at work, or on the go.
अनगिनत पासवर्ड मैनेज, स्टोर, महफूज़, और शेयर करें कही से भी। बिटवार्डन देता है ओपन सोर्स पासवर्ड मैनेजमेंट सुविधा सबको, चाहे वो घर पर हो, दफ्तर पर हो, या घूम रहे हो।
Generate strong, unique, and random passwords based on security requirements for every website you frequent.
आप जिन वेबसाइट पर जाते है उनके लिए बनाएं ताकतवर, खास, और बेतरतीब पासवर्ड उनकी सुरक्षा ज़रूरतो के हिसाब से।
Bitwarden Send quickly transmits encrypted information --- files and plaintext -- directly to anyone.
बिटवार्डन सेंड किसी को भी एन्क्रिप्टेड जानकारी, फाइल और सादा टेक्सट, तुरंत भेजें।
Bitwarden offers Teams and Enterprise plans for companies so you can securely share passwords with colleagues.
बिटवार्डन कंपनियों के लिए टीम और बिज़नेस प्लान भी देता है ताकि आप अपने साथ काम करनेवालो के साथ पासवर्ड शेयर करे सुरक्षित होकर।
Why Choose Bitwarden:
बिटवार्डन को क्यों चुनें:
World-Class Encryption
Passwords are protected with advanced end-to-end encryption (AES-256 bit, salted hashtag, and PBKDF2 SHA-256) so your data stays secure and private.
ताकतवर एन्क्रिप्शन
पासवर्ड एडवांस एंड-टू-एंड एन्क्रिप्शन (एईएस-256 बिट, सॉल्टेड हैशटैग, और पीबीकेडीएफ2 शा-256) के साथ सुरक्षित रखा जाता है ताकि आपका डाटा महफूज़ और निजी रहे।
Built-in Password Generator
Generate strong, unique, and random passwords based on security requirements for every website you frequent.
पहले से बना पासवर्ड जेनरेटर
आप जिन वेबसाइट पर जाते है उनके लिए बनाएं ताकतवर, खास, और बेतरतीब पासवर्ड उनकी सुरक्षा ज़रूरतो के हिसाब से।
Global Translations
Bitwarden translations exist in 40 languages and are growing, thanks to our global community.
अंतरराष्ट्रीय अनुवाद
40 से ज़्यादा भाषा में बिटवार्डन इस्तेमाल करें, जिसे लिखा है हमारी अंतरराष्ट्रीय दोस्तो ने।
Cross-Platform Applications
Secure and share sensitive data within your Bitwarden Vault from any browser, mobile device, or desktop OS, and more.
कई प्लेनफॉर्म पर मौजूद
अपने बिटवार्डन तिजोरी से संवेदनशील डाटा महफूज़ और शेयर करें किसी भी ब्राउज़र, फोन, या डेस्कटॉप जैसे डिवाइसो से।
</value>
<comment>Max 4000 characters</comment>
</data>
<data name="Keywords" xml:space="preserve">
<value>बिटवर्डन, 8 बिट, पासवर्ड, फ्री पासवर्ड मैनेजर, पासवर्ड मैनेजर, लॉगिन मैनेजर</value>
<value>बिटवर्डन, 8 बिट, पासवर्ड, मुफ्त पासवर्ड मैनेजर, पासवर्ड मैनेजर, लॉगइन मैनेजर</value>
<comment>Max 100 characters</comment>
</data>
<data name="Screenshot1" xml:space="preserve">
<value>एक सुरक्षित तिजोरी से अपने सभी लॉगिन और पासवर्ड प्रबंधित करें</value>
<value>एक सुरक्षित तिजोरी से अपने सारे लॉगइन और पासवर्ड मैनेज करें</value>
</data>
<data name="Screenshot2" xml:space="preserve">
<value>स्वचालित रूप से मजबूत, यादृच्छिक और सुरक्षित पासवर्ड उत्पन्न करते हैं</value>
<value>अपनेआप ताकतवर, बेतरतीब, और महफूज़ पासवर्ड बनाएं</value>
</data>
<data name="Screenshot3" xml:space="preserve">
<value>टच आईडी, पिन कोड या मास्टर पासवर्ड से अपनी तिजोरी को सुरक्षित रखें</value>
<value>टच आईडी, पिन कोड, या मुख्य पासवर्ड से अपनी तिजोरी सुरक्षित रखें</value>
</data>
<data name="Screenshot4" xml:space="preserve">
<value>सफारी, क्रोम और अन्य सैकड़ों ऐप्स से ऑटो-फिल लॉगिन करें</value>
<value>सफारी, क्रोम, और सैकड़ों दूसरे ऐप से अपनेआप भरकर लॉगइन करें</value>
</data>
<data name="Screenshot5" xml:space="preserve">
<value>कई उपकरणों से अपने Vault को सिंक और एक्सेस करें</value>
<value>अपने तिजोरी को अलग-अलग डिवाइसो से सिंक और एक्सेस करें</value>
</data>
</root>

View File

@ -118,61 +118,61 @@
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Title" xml:space="preserve">
<value>bitwarden Password Manager</value>
<value>बिटवार्डन पासवर्ड मैनेजर</value>
<comment>Max 30 characters</comment>
</data>
<data name="ShortDescription" xml:space="preserve">
<value>bitwarden is a login and password manager that helps keep you safe while online.</value>
<value>बिटवाडर्न एक लॉगइन और पासवर्ड मैनेजर है जो आपको ऑनलाइन महफूज़ रखता है।</value>
<comment>Max 80 characters</comment>
</data>
<data name="FullDesciption" xml:space="preserve">
<value>Bitwarden, Inc. is the parent company of 8bit Solutions LLC.
<value>बिटवार्डन अंतरराष्ट्रीय कॉरपोरेशन, 8बिट सॉल्यूश्नस एलएलसी की मूल कंपनी है।
NAMED BEST PASSWORD MANAGER BY THE VERGE, U.S. NEWS &amp; WORLD REPORT, CNET, AND MORE.
द वर्ज, यूएस न्यूज़ एंड वर्ल्ड रिपोर्ट, सीनेट, और कई दूसरे मीडिया संगठन द्वारा बोला गया दुनिया का सबसे बेहतरीन पासवर्ड मैनेजर।
Manage, store, secure, and share unlimited passwords across unlimited devices from anywhere. Bitwarden delivers open source password management solutions to everyone, whether at home, at work, or on the go.
अनगिनत पासवर्ड मैनेज, स्टोर, महफूज़, और शेयर करें कही से भी। बिटवार्डन देता है ओपन सोर्स पासवर्ड मैनेजमेंट सुविधा सबको, चाहे वो घर पर हो, दफ्तर पर हो, या घूम रहे हो।
Generate strong, unique, and random passwords based on security requirements for every website you frequent.
आप जिन वेबसाइट पर जाते है उनके लिए बनाएं ताकतवर, खास, और बेतरतीब पासवर्ड उनकी सुरक्षा ज़रूरतो के हिसाब से।
Bitwarden Send quickly transmits encrypted information --- files and plaintext -- directly to anyone.
बिटवार्डन सेंड किसी को भी एन्क्रिप्टेड जानकारी, फाइल और सादा टेक्सट, तुरंत भेजें।
Bitwarden offers Teams and Enterprise plans for companies so you can securely share passwords with colleagues.
बिटवार्डन कंपनियों के लिए टीम और बिज़नेस प्लान भी देता है ताकि आप अपने साथ काम करनेवालो के साथ पासवर्ड शेयर करे सुरक्षित होकर।
Why Choose Bitwarden:
बिटवार्डन को क्यों चुनें:
World-Class Encryption
Passwords are protected with advanced end-to-end encryption (AES-256 bit, salted hashtag, and PBKDF2 SHA-256) so your data stays secure and private.
ताकतवर एन्क्रिप्शन
पासवर्ड एडवांस एंड-टू-एंड एन्क्रिप्शन (एईएस-256 बिट, सॉल्टेड हैशटैग, और पीबीकेडीएफ2 शा-256) के साथ सुरक्षित रखा जाता है ताकि आपका डाटा महफूज़ और निजी रहे।
Built-in Password Generator
Generate strong, unique, and random passwords based on security requirements for every website you frequent.
पहले से बना पासवर्ड जेनरेटर
आप जिन वेबसाइट पर जाते है उनके लिए बनाएं ताकतवर, खास, और बेतरतीब पासवर्ड उनकी सुरक्षा ज़रूरतो के हिसाब से।
Global Translations
Bitwarden translations exist in 40 languages and are growing, thanks to our global community.
अंतरराष्ट्रीय अनुवाद
40 से ज़्यादा भाषा में बिटवार्डन इस्तेमाल करें, जिसे लिखा है हमारी अंतरराष्ट्रीय दोस्तो ने।
Cross-Platform Applications
Secure and share sensitive data within your Bitwarden Vault from any browser, mobile device, or desktop OS, and more.
कई प्लेनफॉर्म पर मौजूद
अपने बिटवार्डन तिजोरी से संवेदनशील डाटा महफूज़ और शेयर करें किसी भी ब्राउज़र, फोन, या डेस्कटॉप जैसे डिवाइसो से।
</value>
<comment>Max 4000 characters</comment>
</data>
<data name="FeatureGraphic" xml:space="preserve">
<value>आपके सभी उपकरणों के लिए एक सुरक्षित और मुफ्त पासवर्ड प्रबंधक</value>
<value>आपके सारे डिवाइसो के लिए एक सुरक्षित और मुफ्त पासवर्ड मैनेजर</value>
</data>
<data name="Screenshot1" xml:space="preserve">
<value>एक सुरक्षित तिजोरी से अपने सभी लॉगिन और पासवर्ड प्रबंधित करें</value>
<value>एक सुरक्षित तिजोरी से अपने सारे लॉगइन और पासवर्ड मैनेज करें</value>
</data>
<data name="Screenshot2" xml:space="preserve">
<value>स्वचालित रूप से मजबूत, यादृच्छिक और सुरक्षित पासवर्ड उत्पन्न करते हैं</value>
<value>अपनेआप ताकतवर, बेतरतीब, और महफूज़ पासवर्ड बनाएं</value>
</data>
<data name="Screenshot3" xml:space="preserve">
<value>टच आईडी, पिन कोड या मास्टर पासवर्ड से अपनी तिजोरी को सुरक्षित रखें</value>
<value>फिंगरप्रिंट, पिन कोड, या मुख्य पासवर्ड से अपनी तिजोरी सुरक्षित रखें</value>
</data>
<data name="Screenshot4" xml:space="preserve">
<value>अपने वेब ब्राउज़र और अन्य एप्लिकेशन के भीतर से जल्दी से लॉगिन करें</value>
<value>अपने वेब ब्राउज़र और दूसरे ऐप से जल्दी लॉगइन करें</value>
</data>
<data name="Screenshot5" xml:space="preserve">
<value>कई उपकरणों से अपने वॉल्ट को सिंक और एक्सेस करें
<value>अपने तिजोरी को अलग-अलग डिवाइसों से सिंक और एक्सेस करें
- फोन
- फोन
- टैबलेट
- डेस्कटॉप
- वेब</value>