mirror of
https://github.com/bitwarden/mobile.git
synced 2024-09-27 03:52:57 +02:00
Merge branch 'main' into feature/maui-migration-passkeys
# Conflicts: # src/Core/Abstractions/ICipherService.cs # src/Core/Abstractions/IStateService.cs # src/Core/Models/AppOptions.cs # src/Core/Resources/Localization/AppResources.resx # src/Core/Utilities/ServiceContainer.cs # src/iOS.Autofill/iOS.Autofill.csproj
This commit is contained in:
commit
76e0f7e1a4
4
.github/workflows/build-beta.yml
vendored
4
.github/workflows/build-beta.yml
vendored
@ -63,7 +63,7 @@ jobs:
|
||||
nuget-version: 6.4.0
|
||||
|
||||
- name: Set up .NET
|
||||
uses: actions/setup-dotnet@3447fd6a9f9e57506b15f895c5b76d3b197dc7c2 # v3.2.0
|
||||
uses: actions/setup-dotnet@4d6c8fcf3c8f7a60068d26b594648e99df24cee3 # v4.0.0
|
||||
with:
|
||||
dotnet-version: '8.0.x'
|
||||
|
||||
@ -342,7 +342,7 @@ jobs:
|
||||
secrets: "devops-alerts-slack-webhook-url"
|
||||
|
||||
- name: Notify Slack on failure
|
||||
uses: act10ns/slack@ed1309ab9862e57e9e583e51c7889486b9a00b0f # v2.0.0
|
||||
uses: act10ns/slack@44541246747a30eb3102d87f7a4cc5471b0ffb7d # v2.1.0
|
||||
if: failure()
|
||||
env:
|
||||
SLACK_WEBHOOK_URL: ${{ steps.retrieve-secrets.outputs.devops-alerts-slack-webhook-url }}
|
||||
|
8
.github/workflows/build.yml
vendored
8
.github/workflows/build.yml
vendored
@ -305,7 +305,7 @@ jobs:
|
||||
nuget-version: 6.4.0
|
||||
|
||||
- name: Set up .NET
|
||||
uses: actions/setup-dotnet@3447fd6a9f9e57506b15f895c5b76d3b197dc7c2 # v3.2.0
|
||||
uses: actions/setup-dotnet@4d6c8fcf3c8f7a60068d26b594648e99df24cee3 # v4.0.0
|
||||
with:
|
||||
dotnet-version: '8.0.x'
|
||||
|
||||
@ -453,7 +453,7 @@ jobs:
|
||||
nuget-version: 6.4.0
|
||||
|
||||
- name: Set up .NET
|
||||
uses: actions/setup-dotnet@3447fd6a9f9e57506b15f895c5b76d3b197dc7c2 # v3.2.0
|
||||
uses: actions/setup-dotnet@4d6c8fcf3c8f7a60068d26b594648e99df24cee3 # v4.0.0
|
||||
with:
|
||||
dotnet-version: '8.0.x'
|
||||
|
||||
@ -733,7 +733,7 @@ jobs:
|
||||
secrets: "crowdin-api-token"
|
||||
|
||||
- name: Upload Sources
|
||||
uses: crowdin/github-action@c953b17499daa6be3e5afbf7a63616fb02d8b18d # v1.19.0
|
||||
uses: crowdin/github-action@67705afb6985401459cd143d5f5f00c9dc212f23 # v1.20.2
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
CROWDIN_API_TOKEN: ${{ steps.retrieve-secrets.outputs.crowdin-api-token }}
|
||||
@ -778,7 +778,7 @@ jobs:
|
||||
secrets: "devops-alerts-slack-webhook-url"
|
||||
|
||||
- name: Notify Slack on failure
|
||||
uses: act10ns/slack@ed1309ab9862e57e9e583e51c7889486b9a00b0f # v2.0.0
|
||||
uses: act10ns/slack@44541246747a30eb3102d87f7a4cc5471b0ffb7d # v2.1.0
|
||||
if: failure()
|
||||
env:
|
||||
SLACK_WEBHOOK_URL: ${{ steps.retrieve-secrets.outputs.devops-alerts-slack-webhook-url }}
|
||||
|
2
.github/workflows/crowdin-pull.yml
vendored
2
.github/workflows/crowdin-pull.yml
vendored
@ -30,7 +30,7 @@ jobs:
|
||||
secrets: "crowdin-api-token, github-gpg-private-key, github-gpg-private-key-passphrase"
|
||||
|
||||
- name: Download translations
|
||||
uses: crowdin/github-action@c953b17499daa6be3e5afbf7a63616fb02d8b18d # v1.19.0
|
||||
uses: crowdin/github-action@67705afb6985401459cd143d5f5f00c9dc212f23 # v1.20.2
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
CROWDIN_API_TOKEN: ${{ steps.retrieve-secrets.outputs.crowdin-api-token }}
|
||||
|
8
.github/workflows/release.yml
vendored
8
.github/workflows/release.yml
vendored
@ -68,7 +68,7 @@ jobs:
|
||||
|
||||
- name: Download all artifacts
|
||||
if: ${{ inputs.release_type != 'Dry Run' }}
|
||||
uses: dawidd6/action-download-artifact@71072fbb1229e1317f1a8de6b04206afb461bd67 # v3.1.2
|
||||
uses: dawidd6/action-download-artifact@09f2f74827fd3a8607589e5ad7f9398816f540fe # v3.1.4
|
||||
with:
|
||||
workflow: build.yml
|
||||
workflow_conclusion: success
|
||||
@ -76,7 +76,7 @@ jobs:
|
||||
|
||||
- name: Dry Run - Download all artifacts
|
||||
if: ${{ inputs.release_type == 'Dry Run' }}
|
||||
uses: dawidd6/action-download-artifact@71072fbb1229e1317f1a8de6b04206afb461bd67 # v3.1.2
|
||||
uses: dawidd6/action-download-artifact@09f2f74827fd3a8607589e5ad7f9398816f540fe # v3.1.4
|
||||
with:
|
||||
workflow: build.yml
|
||||
workflow_conclusion: success
|
||||
@ -130,7 +130,7 @@ jobs:
|
||||
|
||||
- name: Download F-Droid .apk artifact
|
||||
if: ${{ inputs.release_type != 'Dry Run' }}
|
||||
uses: dawidd6/action-download-artifact@71072fbb1229e1317f1a8de6b04206afb461bd67 # v3.1.2
|
||||
uses: dawidd6/action-download-artifact@09f2f74827fd3a8607589e5ad7f9398816f540fe # v3.1.4
|
||||
with:
|
||||
workflow: build.yml
|
||||
workflow_conclusion: success
|
||||
@ -139,7 +139,7 @@ jobs:
|
||||
|
||||
- name: Dry Run - Download F-Droid .apk artifact
|
||||
if: ${{ inputs.release_type == 'Dry Run' }}
|
||||
uses: dawidd6/action-download-artifact@71072fbb1229e1317f1a8de6b04206afb461bd67 # v3.1.2
|
||||
uses: dawidd6/action-download-artifact@09f2f74827fd3a8607589e5ad7f9398816f540fe # v3.1.4
|
||||
with:
|
||||
workflow: build.yml
|
||||
workflow_conclusion: success
|
||||
|
@ -260,4 +260,7 @@
|
||||
<None Remove="Platforms\iOS\Resources\logo%402x.png" />
|
||||
<None Remove="Platforms\Android\Resources\drawable-xxxhdpi\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">
|
||||
<BundleResource Include="Platforms\iOS\PrivacyInfo.xcprivacy" LogicalName="PrivacyInfo.xcprivacy" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:versionCode="1" android:versionName="2024.4.0" android:installLocation="internalOnly" package="com.x8bit.bitwarden">
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:versionCode="1" android:versionName="2024.4.1" android:installLocation="internalOnly" package="com.x8bit.bitwarden">
|
||||
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="34" />
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.NFC" />
|
||||
|
@ -11,7 +11,7 @@
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.8bit.bitwarden</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>2024.4.0</string>
|
||||
<string>2024.4.1</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>CFBundleIconName</key>
|
||||
|
41
src/App/Platforms/iOS/PrivacyInfo.xcprivacy
Normal file
41
src/App/Platforms/iOS/PrivacyInfo.xcprivacy
Normal file
@ -0,0 +1,41 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>NSPrivacyAccessedAPITypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>NSPrivacyAccessedAPIType</key>
|
||||
<string>NSPrivacyAccessedAPICategoryFileTimestamp</string>
|
||||
<key>NSPrivacyAccessedAPITypeReasons</key>
|
||||
<array>
|
||||
<string>C617.1</string>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>NSPrivacyAccessedAPIType</key>
|
||||
<string>NSPrivacyAccessedAPICategorySystemBootTime</string>
|
||||
<key>NSPrivacyAccessedAPITypeReasons</key>
|
||||
<array>
|
||||
<string>35F9.1</string>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>NSPrivacyAccessedAPIType</key>
|
||||
<string>NSPrivacyAccessedAPICategoryDiskSpace</string>
|
||||
<key>NSPrivacyAccessedAPITypeReasons</key>
|
||||
<array>
|
||||
<string>E174.1</string>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>NSPrivacyAccessedAPIType</key>
|
||||
<string>NSPrivacyAccessedAPICategoryUserDefaults</string>
|
||||
<key>NSPrivacyAccessedAPITypeReasons</key>
|
||||
<array>
|
||||
<string>1C8F.1</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
@ -46,6 +46,7 @@ namespace Bit.Core.Abstractions
|
||||
Task<CipherResponse> PutShareCipherAsync(string id, CipherShareRequest request);
|
||||
Task PutDeleteCipherAsync(string id);
|
||||
Task<CipherResponse> PutRestoreCipherAsync(string id);
|
||||
Task<bool> HasUnassignedCiphersAsync();
|
||||
Task RefreshIdentityTokenAsync();
|
||||
Task<SsoPrevalidateResponse> PreValidateSsoAsync(string identifier);
|
||||
Task<TResponse> SendAsync<TRequest, TResponse>(HttpMethod method, string path,
|
||||
|
@ -36,5 +36,6 @@ namespace Bit.Core.Abstractions
|
||||
Task RestoreWithServerAsync(string id);
|
||||
Task<string> CreateNewLoginForPasskeyAsync(Fido2ConfirmNewCredentialParams newPasskeyParams);
|
||||
Task CopyTotpCodeIfNeededAsync(CipherView cipher);
|
||||
Task<bool> VerifyOrganizationHasUnassignedItemsAsync();
|
||||
}
|
||||
}
|
||||
|
@ -187,6 +187,8 @@ namespace Bit.Core.Abstractions
|
||||
Task<BwRegion?> GetPreAuthRegionAsync();
|
||||
Task SetPreAuthRegionAsync(BwRegion value);
|
||||
Task ReloadStateAsync();
|
||||
Task<bool> GetShouldCheckOrganizationUnassignedItemsAsync(string userId = null);
|
||||
Task SetShouldCheckOrganizationUnassignedItemsAsync(bool shouldCheck, string userId = null);
|
||||
[Obsolete("Use GetPinKeyEncryptedUserKeyAsync instead, left for migration purposes")]
|
||||
Task<string> GetPinProtectedAsync(string userId = null);
|
||||
[Obsolete("Use SetPinKeyEncryptedUserKeyAsync instead, left for migration purposes")]
|
||||
|
@ -46,6 +46,7 @@ namespace Bit.Core
|
||||
public const string PreLoginEmailKey = "preLoginEmailKey";
|
||||
public const string ConfigsKey = "configsKey";
|
||||
public const string DisplayEuEnvironmentFlag = "display-eu-environment";
|
||||
public const string UnassignedItemsBannerFlag = "unassigned-items-banner";
|
||||
public const string RegionEnvironment = "regionEnvironment";
|
||||
public const string DuoCallback = "bitwarden://duo-callback";
|
||||
public const string NavigateToMessageCommand = "navigateTo";
|
||||
@ -138,6 +139,7 @@ namespace Bit.Core
|
||||
public static string ShouldConnectToWatchKey(string userId) => $"shouldConnectToWatch_{userId}";
|
||||
public static string ScreenCaptureAllowedKey(string userId) => $"screenCaptureAllowed_{userId}";
|
||||
public static string PendingAdminAuthRequest(string userId) => $"pendingAdminAuthRequest_{userId}";
|
||||
public static string ShouldCheckOrganizationUnassignedItemsKey(string userId) => $"shouldCheckOrganizationUnassignedItems_{userId}";
|
||||
[Obsolete]
|
||||
public static string KeyKey(string userId) => $"key_{userId}";
|
||||
[Obsolete]
|
||||
|
@ -27,6 +27,7 @@ namespace Bit.App.Models
|
||||
public bool HideAccountSwitcher { get; set; }
|
||||
public OtpData? OtpData { get; set; }
|
||||
public bool HasUnlockedInThisTransaction { get; set; }
|
||||
public bool HasJustLoggedInOrUnlocked { get; set; }
|
||||
|
||||
public void SetAllFrom(AppOptions o)
|
||||
{
|
||||
|
@ -233,6 +233,7 @@ namespace Bit.App.Pages
|
||||
}
|
||||
var previousPage = await AppHelpers.ClearPreviousPage();
|
||||
|
||||
_appOptions.HasJustLoggedInOrUnlocked = true;
|
||||
App.MainPage = new TabsPage(_appOptions, previousPage);
|
||||
}
|
||||
}
|
||||
|
@ -35,6 +35,8 @@ namespace Bit.App.Pages
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_appOptions.HasJustLoggedInOrUnlocked = true;
|
||||
var previousPage = await AppHelpers.ClearPreviousPage();
|
||||
App.MainPage = new TabsPage(_appOptions, previousPage);
|
||||
}
|
||||
|
@ -195,6 +195,8 @@ namespace Bit.App.Pages
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_appOptions.HasJustLoggedInOrUnlocked = true;
|
||||
var previousPage = await AppHelpers.ClearPreviousPage();
|
||||
App.MainPage = new TabsPage(_appOptions, previousPage);
|
||||
}
|
||||
|
@ -55,6 +55,8 @@ namespace Bit.App.Pages
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_appOptions.HasJustLoggedInOrUnlocked = true;
|
||||
var previousPage = await AppHelpers.ClearPreviousPage();
|
||||
App.MainPage = new TabsPage(_appOptions, previousPage);
|
||||
}
|
||||
|
@ -71,6 +71,8 @@ namespace Bit.App.Pages
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_appOptions.HasJustLoggedInOrUnlocked = true;
|
||||
var previousPage = await AppHelpers.ClearPreviousPage();
|
||||
App.MainPage = new TabsPage(_appOptions, previousPage);
|
||||
}
|
||||
|
@ -206,6 +206,8 @@ namespace Bit.App.Pages
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_appOptions.HasJustLoggedInOrUnlocked = true;
|
||||
var previousPage = await AppHelpers.ClearPreviousPage();
|
||||
App.MainPage = new TabsPage(_appOptions, previousPage);
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ namespace Bit.App.Pages
|
||||
_keyConnectorService = ServiceContainer.Resolve<IKeyConnectorService>("keyConnectorService");
|
||||
_stateService = ServiceContainer.Resolve<IStateService>();
|
||||
|
||||
_groupingsPage = new NavigationPage(new GroupingsPage(true, previousPage: previousPage))
|
||||
_groupingsPage = new NavigationPage(new GroupingsPage(true, previousPage: previousPage, appOptions: appOptions))
|
||||
{
|
||||
Title = AppResources.MyVault,
|
||||
IconImageSource = "lock.png"
|
||||
|
@ -1,5 +1,6 @@
|
||||
using Bit.App.Abstractions;
|
||||
using Bit.App.Controls;
|
||||
using Bit.App.Models;
|
||||
using Bit.Core.Abstractions;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Models.Data;
|
||||
@ -27,7 +28,7 @@ namespace Bit.App.Pages
|
||||
|
||||
public GroupingsPage(bool mainPage, CipherType? type = null, string folderId = null,
|
||||
string collectionId = null, string pageTitle = null, string vaultFilterSelection = null,
|
||||
PreviousPageInfo previousPage = null, bool deleted = false, bool showTotp = false)
|
||||
PreviousPageInfo previousPage = null, bool deleted = false, bool showTotp = false, AppOptions appOptions = null)
|
||||
{
|
||||
_pageName = string.Concat(nameof(GroupingsPage), "_", DateTime.UtcNow.Ticks);
|
||||
InitializeComponent();
|
||||
@ -50,6 +51,7 @@ namespace Bit.App.Pages
|
||||
_vm.CollectionId = collectionId;
|
||||
_vm.Deleted = deleted;
|
||||
_vm.ShowTotp = showTotp;
|
||||
_vm.AppOptions = appOptions;
|
||||
_previousPage = previousPage;
|
||||
if (pageTitle != null)
|
||||
{
|
||||
@ -160,6 +162,8 @@ namespace Bit.App.Pages
|
||||
return;
|
||||
}
|
||||
|
||||
await _vm.CheckOrganizationUnassignedItemsAsync();
|
||||
|
||||
// Push registration
|
||||
var lastPushRegistration = await _stateService.GetPushLastRegistrationDateAsync();
|
||||
lastPushRegistration = lastPushRegistration.GetValueOrDefault(DateTime.MinValue);
|
||||
|
@ -1,6 +1,7 @@
|
||||
using System.Windows.Input;
|
||||
using Bit.App.Abstractions;
|
||||
using Bit.App.Controls;
|
||||
using Bit.App.Models;
|
||||
using Bit.App.Utilities;
|
||||
using Bit.Core.Abstractions;
|
||||
using Bit.Core.Enums;
|
||||
@ -45,6 +46,8 @@ namespace Bit.App.Pages
|
||||
private readonly IPasswordRepromptService _passwordRepromptService;
|
||||
private readonly IOrganizationService _organizationService;
|
||||
private readonly IPolicyService _policyService;
|
||||
private readonly IConfigService _configService;
|
||||
private readonly IEnvironmentService _environmentService;
|
||||
private readonly ILogger _logger;
|
||||
|
||||
public GroupingsPageViewModel()
|
||||
@ -61,6 +64,8 @@ namespace Bit.App.Pages
|
||||
_passwordRepromptService = ServiceContainer.Resolve<IPasswordRepromptService>("passwordRepromptService");
|
||||
_organizationService = ServiceContainer.Resolve<IOrganizationService>("organizationService");
|
||||
_policyService = ServiceContainer.Resolve<IPolicyService>("policyService");
|
||||
_configService = ServiceContainer.Resolve<IConfigService>();
|
||||
_environmentService = ServiceContainer.Resolve<IEnvironmentService>();
|
||||
_logger = ServiceContainer.Resolve<ILogger>("logger");
|
||||
|
||||
Loading = true;
|
||||
@ -104,6 +109,7 @@ namespace Bit.App.Pages
|
||||
public List<Core.Models.View.CollectionView> Collections { get; set; }
|
||||
public List<TreeNode<Core.Models.View.CollectionView>> NestedCollections { get; set; }
|
||||
|
||||
public AppOptions AppOptions { get; internal set; }
|
||||
protected override ICipherService cipherService => _cipherService;
|
||||
protected override IPolicyService policyService => _policyService;
|
||||
protected override IOrganizationService organizationService => _organizationService;
|
||||
@ -699,5 +705,59 @@ namespace Bit.App.Pages
|
||||
var folders = decFolders.Where(f => _allCiphers.Any(c => c.FolderId == f.Id)).ToList();
|
||||
return folders.Any() ? folders : null;
|
||||
}
|
||||
|
||||
internal async Task CheckOrganizationUnassignedItemsAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (AppOptions?.HasJustLoggedInOrUnlocked != true)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AppOptions.HasJustLoggedInOrUnlocked = false;
|
||||
|
||||
if (!await _configService.GetFeatureFlagBoolAsync(Core.Constants.UnassignedItemsBannerFlag)
|
||||
||
|
||||
!await _stateService.GetShouldCheckOrganizationUnassignedItemsAsync())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var waitSyncTask = Task.Run(async () =>
|
||||
{
|
||||
while (_syncService.SyncInProgress)
|
||||
{
|
||||
await Task.Delay(100);
|
||||
}
|
||||
});
|
||||
await waitSyncTask.WaitAsync(TimeSpan.FromMinutes(5));
|
||||
|
||||
if (!await _cipherService.VerifyOrganizationHasUnassignedItemsAsync())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var message = _environmentService.SelectedRegion == Core.Enums.Region.SelfHosted
|
||||
? AppResources.OrganizationUnassignedItemsMessageSelfHost041624DescriptionLong
|
||||
: AppResources.OrganizationUnassignedItemsMessageUSEUDescriptionLong;
|
||||
|
||||
var response = await _deviceActionService.DisplayAlertAsync(AppResources.Notice,
|
||||
message,
|
||||
null,
|
||||
AppResources.RemindMeLater,
|
||||
AppResources.Ok);
|
||||
|
||||
if (response == AppResources.Ok)
|
||||
{
|
||||
await _stateService.SetShouldCheckOrganizationUnassignedItemsAsync(false);
|
||||
}
|
||||
}
|
||||
catch (TimeoutException) { }
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Exception(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4929,6 +4929,15 @@ namespace Bit.Core.Resources.Localization {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Notice.
|
||||
/// </summary>
|
||||
public static string Notice {
|
||||
get {
|
||||
return ResourceManager.GetString("Notice", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to This account has two-step login set up, however, none of the configured two-step providers are supported on this device. Please use a supported device and/or add additional providers that are better supported across devices (such as an authenticator app)..
|
||||
/// </summary>
|
||||
@ -5164,6 +5173,24 @@ namespace Bit.Core.Resources.Localization {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to On May 16, 2024, unassigned organization items will no longer be visible in the All Vaults view and only accessible via the Admin Console. Assign these items to a collection from the Admin Console to make them visible..
|
||||
/// </summary>
|
||||
public static string OrganizationUnassignedItemsMessageSelfHost041624DescriptionLong {
|
||||
get {
|
||||
return ResourceManager.GetString("OrganizationUnassignedItemsMessageSelfHost041624DescriptionLong", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Unassigned organization items are no longer visible in the All Vaults view and only accessible via the Admin Console. Assign these items to a collection from the Admin Console to make them visible..
|
||||
/// </summary>
|
||||
public static string OrganizationUnassignedItemsMessageUSEUDescriptionLong {
|
||||
get {
|
||||
return ResourceManager.GetString("OrganizationUnassignedItemsMessageUSEUDescriptionLong", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Organization identifier.
|
||||
/// </summary>
|
||||
@ -5795,6 +5822,15 @@ namespace Bit.Core.Resources.Localization {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Remind me later.
|
||||
/// </summary>
|
||||
public static string RemindMeLater {
|
||||
get {
|
||||
return ResourceManager.GetString("RemindMeLater", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Remove.
|
||||
/// </summary>
|
||||
|
@ -560,7 +560,7 @@
|
||||
<comment>Message shown when interacting with the server</comment>
|
||||
</data>
|
||||
<data name="LoginOrCreateNewAccount" xml:space="preserve">
|
||||
<value>Käytä salattua holviasi kirjautumalla sisään tai tai luo uusi tili.</value>
|
||||
<value>Käytä salattua holviasi kirjautumalla sisään tai luo uusi tili.</value>
|
||||
</data>
|
||||
<data name="Manage" xml:space="preserve">
|
||||
<value>Hallinta</value>
|
||||
|
@ -2877,12 +2877,12 @@ Vuoi passare a questo account?</value>
|
||||
<value>Imposta un metodo di sblocco per modificare l'azione timeout cassaforte.</value>
|
||||
</data>
|
||||
<data name="DuoTwoStepLoginIsRequiredForYourAccount" xml:space="preserve">
|
||||
<value>Duo two-step login is required for your account. </value>
|
||||
<value>Per il tuo account è richiesta la verifica in due passaggi di Duo.</value>
|
||||
</data>
|
||||
<data name="FollowTheStepsFromDuoToFinishLoggingIn" xml:space="preserve">
|
||||
<value>Follow the steps from Duo to finish logging in.</value>
|
||||
<value>Segui i passaggi da Duo per completare l'accesso.</value>
|
||||
</data>
|
||||
<data name="LaunchDuo" xml:space="preserve">
|
||||
<value>Launch Duo</value>
|
||||
<value>Avvia Duo</value>
|
||||
</data>
|
||||
</root>
|
||||
|
@ -2975,4 +2975,16 @@ Do you want to switch to this account?</value>
|
||||
<data name="YourPasskeyWillBeSavedToYourBitwardenVaultForX" xml:space="preserve">
|
||||
<value>Your passkey will be saved to your Bitwarden vault for {0}</value>
|
||||
</data>
|
||||
<data name="OrganizationUnassignedItemsMessageUSEUDescriptionLong" xml:space="preserve">
|
||||
<value>Unassigned organization items are no longer visible in the All Vaults view and only accessible via the Admin Console. Assign these items to a collection from the Admin Console to make them visible.</value>
|
||||
</data>
|
||||
<data name="OrganizationUnassignedItemsMessageSelfHost041624DescriptionLong" xml:space="preserve">
|
||||
<value>On May 16, 2024, unassigned organization items will no longer be visible in the All Vaults view and only accessible via the Admin Console. Assign these items to a collection from the Admin Console to make them visible.</value>
|
||||
</data>
|
||||
<data name="RemindMeLater" xml:space="preserve">
|
||||
<value>Remind me later</value>
|
||||
</data>
|
||||
<data name="Notice" xml:space="preserve">
|
||||
<value>Notice</value>
|
||||
</data>
|
||||
</root>
|
||||
|
@ -2641,22 +2641,22 @@
|
||||
<value>Запомнить это устройство</value>
|
||||
</data>
|
||||
<data name="Passkey" xml:space="preserve">
|
||||
<value>Ключ доступа</value>
|
||||
<value>Passkey</value>
|
||||
</data>
|
||||
<data name="Passkeys" xml:space="preserve">
|
||||
<value>Ключи доступа</value>
|
||||
<value>Passkeys</value>
|
||||
</data>
|
||||
<data name="Application" xml:space="preserve">
|
||||
<value>Приложение</value>
|
||||
</data>
|
||||
<data name="YouCannotEditPasskeyApplicationBecauseItWouldInvalidateThePasskey" xml:space="preserve">
|
||||
<value>Редактирование ключа доступа невозможно, поскольку это приведет к его аннулированию</value>
|
||||
<value>Редактирование passkey невозможно, поскольку это приведет к его аннулированию</value>
|
||||
</data>
|
||||
<data name="PasskeyWillNotBeCopied" xml:space="preserve">
|
||||
<value>Ключ доступа не будет скопирован</value>
|
||||
<value>Passkey не будет скопирован</value>
|
||||
</data>
|
||||
<data name="ThePasskeyWillNotBeCopiedToTheClonedItemDoYouWantToContinueCloningThisItem" xml:space="preserve">
|
||||
<value>Ключ доступа не будет скопирован в клонированный элемент. Продолжить клонирование этого элемента?</value>
|
||||
<value>Passkey не будет скопирован в клонированный элемент. Продолжить клонирование этого элемента?</value>
|
||||
</data>
|
||||
<data name="CopyApplication" xml:space="preserve">
|
||||
<value>Скопировать приложение</value>
|
||||
|
@ -1143,7 +1143,7 @@ Quá trình quét sẽ diễn ra tự động.</value>
|
||||
<value>Địa chỉ biểu tượng máy chủ</value>
|
||||
</data>
|
||||
<data name="AutofillWithBitwarden" xml:space="preserve">
|
||||
<value>Tự động điền với Bitwarden</value>
|
||||
<value>Tự động điền bằng Bitwarden</value>
|
||||
</data>
|
||||
<data name="VaultIsLocked" xml:space="preserve">
|
||||
<value>Kho đã khóa</value>
|
||||
|
@ -334,6 +334,11 @@ namespace Bit.Core.Services
|
||||
return SendAsync<object, CipherResponse>(HttpMethod.Put, string.Concat("/ciphers/", id, "/restore"), null, true, true);
|
||||
}
|
||||
|
||||
public Task<bool> HasUnassignedCiphersAsync()
|
||||
{
|
||||
return SendAsync<object, bool>(HttpMethod.Get, "/ciphers/has-unassigned-ciphers", null, true, true);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Attachments APIs
|
||||
|
@ -835,6 +835,24 @@ namespace Bit.Core.Services
|
||||
await ClearCacheAsync();
|
||||
}
|
||||
|
||||
public async Task<bool> VerifyOrganizationHasUnassignedItemsAsync()
|
||||
{
|
||||
var organizations = await _stateService.GetOrganizationsAsync();
|
||||
if (organizations?.Any() != true)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return await _apiService.HasUnassignedCiphersAsync();
|
||||
}
|
||||
catch (ApiException ex) when (ex.Error?.StatusCode == System.Net.HttpStatusCode.BadRequest)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Helpers
|
||||
|
||||
private async Task<Tuple<SymmetricCryptoKey, EncString, SymmetricCryptoKey>> MakeAttachmentKeyAsync(string organizationId, Cipher cipher = null, CipherView cipherView = null)
|
||||
|
@ -1384,6 +1384,16 @@ namespace Bit.Core.Services
|
||||
await _storageMediatorService.SaveAsync(Constants.RegionEnvironment, value);
|
||||
}
|
||||
|
||||
public async Task<bool> GetShouldCheckOrganizationUnassignedItemsAsync(string userId = null)
|
||||
{
|
||||
return await _storageMediatorService.GetAsync<bool?>(await ComposeKeyAsync(Constants.ShouldCheckOrganizationUnassignedItemsKey, userId)) ?? true;
|
||||
}
|
||||
|
||||
public async Task SetShouldCheckOrganizationUnassignedItemsAsync(bool shouldCheck, string userId = null)
|
||||
{
|
||||
await _storageMediatorService.SaveAsync<bool?>(await ComposeKeyAsync(Constants.ShouldCheckOrganizationUnassignedItemsKey, userId), shouldCheck);
|
||||
}
|
||||
|
||||
// Helpers
|
||||
|
||||
[Obsolete("Use IStorageMediatorService instead")]
|
||||
|
@ -45,6 +45,7 @@ namespace Bit.Core.Utilities
|
||||
var fileUploadService = new FileUploadService(apiService);
|
||||
var configService = new ConfigService(apiService, stateService, logger);
|
||||
var totpService = new TotpService(cryptoFunctionService);
|
||||
var environmentService = new EnvironmentService(apiService, stateService, conditionedRunner);
|
||||
var cipherService = new CipherService(cryptoService, stateService, settingsService, apiService,
|
||||
fileUploadService, storageService, i18nService, () => searchService, configService, totpService, clipboardService, clearCipherCacheKey,
|
||||
allClearCipherCacheKeys);
|
||||
@ -85,7 +86,6 @@ namespace Bit.Core.Utilities
|
||||
keyConnectorService, passwordGenerationService, policyService, deviceTrustCryptoService, passwordResetEnrollmentService);
|
||||
var exportService = new ExportService(folderService, cipherService, cryptoService);
|
||||
var auditService = new AuditService(cryptoFunctionService, apiService);
|
||||
var environmentService = new EnvironmentService(apiService, stateService, conditionedRunner);
|
||||
var eventService = new EventService(apiService, stateService, organizationService, cipherService);
|
||||
var usernameGenerationService = new UsernameGenerationService(cryptoService, apiService, stateService);
|
||||
|
||||
|
@ -11,7 +11,7 @@
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.8bit.bitwarden.autofill</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>2024.4.0</string>
|
||||
<string>2024.4.1</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>CFBundleLocalizations</key>
|
||||
|
@ -195,4 +195,7 @@
|
||||
<ItemGroup>
|
||||
<Folder Include="ListItems\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<BundleResource Include="..\App\Platforms\iOS\PrivacyInfo.xcprivacy" LogicalName="PrivacyInfo.xcprivacy" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
@ -11,7 +11,7 @@
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.8bit.bitwarden.find-login-action-extension</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>2024.4.0</string>
|
||||
<string>2024.4.1</string>
|
||||
<key>CFBundleLocalizations</key>
|
||||
<array>
|
||||
<string>en</string>
|
||||
|
@ -147,4 +147,7 @@
|
||||
<Link>Resources\ext-icon%403x.png</Link>
|
||||
</BundleResource>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<BundleResource Include="..\App\Platforms\iOS\PrivacyInfo.xcprivacy" LogicalName="PrivacyInfo.xcprivacy" />
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -15,7 +15,7 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>XPC!</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>2024.4.0</string>
|
||||
<string>2024.4.1</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>MinimumOSVersion</key>
|
||||
|
@ -110,4 +110,7 @@
|
||||
<ProjectReference Include="..\Core\Core.csproj" />
|
||||
<ProjectReference Include="..\iOS.Core\iOS.Core.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<BundleResource Include="..\App\Platforms\iOS\PrivacyInfo.xcprivacy" LogicalName="PrivacyInfo.xcprivacy" />
|
||||
</ItemGroup>
|
||||
</Project>
|
41
src/watchOS/bitwarden/PrivacyInfo.xcprivacy
Normal file
41
src/watchOS/bitwarden/PrivacyInfo.xcprivacy
Normal file
@ -0,0 +1,41 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>NSPrivacyAccessedAPITypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>NSPrivacyAccessedAPIType</key>
|
||||
<string>NSPrivacyAccessedAPICategoryFileTimestamp</string>
|
||||
<key>NSPrivacyAccessedAPITypeReasons</key>
|
||||
<array>
|
||||
<string>C617.1</string>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>NSPrivacyAccessedAPIType</key>
|
||||
<string>NSPrivacyAccessedAPICategorySystemBootTime</string>
|
||||
<key>NSPrivacyAccessedAPITypeReasons</key>
|
||||
<array>
|
||||
<string>35F9.1</string>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>NSPrivacyAccessedAPIType</key>
|
||||
<string>NSPrivacyAccessedAPICategoryDiskSpace</string>
|
||||
<key>NSPrivacyAccessedAPITypeReasons</key>
|
||||
<array>
|
||||
<string>E174.1</string>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>NSPrivacyAccessedAPIType</key>
|
||||
<string>NSPrivacyAccessedAPICategoryUserDefaults</string>
|
||||
<key>NSPrivacyAccessedAPITypeReasons</key>
|
||||
<array>
|
||||
<string>1C8F.1</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
@ -84,6 +84,8 @@
|
||||
1BDBFEB3290B5D07009C78C7 /* CoreDataHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1BDBFEB2290B5D07009C78C7 /* CoreDataHelper.swift */; };
|
||||
1BF5F6DB29103066002DDC0C /* CipherService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1BF5F6DA29103066002DDC0C /* CipherService.swift */; };
|
||||
1BF5F6DE29103B86002DDC0C /* CipherServiceMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1BF5F6DD29103B86002DDC0C /* CipherServiceMock.swift */; };
|
||||
B7A3ABF42BCEECD700A07178 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = B7A3ABF32BCEECD700A07178 /* PrivacyInfo.xcprivacy */; };
|
||||
B7A3ABF52BCEECD700A07178 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = B7A3ABF32BCEECD700A07178 /* PrivacyInfo.xcprivacy */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
@ -267,6 +269,7 @@
|
||||
B78CEC832A25455400539F0D /* vi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = vi; path = vi.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||
B78CEC842A25455D00539F0D /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Localizable.strings"; sourceTree = "<group>"; };
|
||||
B78CEC852A25456400539F0D /* zh-Hant */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant"; path = "zh-Hant.lproj/Localizable.strings"; sourceTree = "<group>"; };
|
||||
B7A3ABF32BCEECD700A07178 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
@ -322,6 +325,7 @@
|
||||
1B15612628B7F3D400610B9B = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B7A3ABF32BCEECD700A07178 /* PrivacyInfo.xcprivacy */,
|
||||
1B5BE45D295B472C00E0C323 /* GoogleService-Info.plist */,
|
||||
1B15613128B7F3D400610B9B /* bitwarden */,
|
||||
1B15614128B7F3D700610B9B /* bitwarden WatchKit App */,
|
||||
@ -727,6 +731,7 @@
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
B7A3ABF42BCEECD700A07178 /* PrivacyInfo.xcprivacy in Resources */,
|
||||
1B15614328B7F3D800610B9B /* Assets.xcassets in Resources */,
|
||||
1B5BE45F295B472C00E0C323 /* GoogleService-Info.plist in Resources */,
|
||||
);
|
||||
@ -739,6 +744,7 @@
|
||||
1B15615B28B7F3D900610B9B /* Preview Assets.xcassets in Resources */,
|
||||
1B5BE460295B472C00E0C323 /* GoogleService-Info.plist in Resources */,
|
||||
1B5AFF0729197822004478F9 /* Localizable.strings in Resources */,
|
||||
B7A3ABF52BCEECD700A07178 /* PrivacyInfo.xcprivacy in Resources */,
|
||||
1B15615828B7F3D900610B9B /* Assets.xcassets in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
|
Loading…
Reference in New Issue
Block a user