diff --git a/src/Api/Vault/Controllers/CiphersController.cs b/src/Api/Vault/Controllers/CiphersController.cs
index cd70d7a6c0..efc9a0eb88 100644
--- a/src/Api/Vault/Controllers/CiphersController.cs
+++ b/src/Api/Vault/Controllers/CiphersController.cs
@@ -1110,6 +1110,33 @@ public class CiphersController : Controller
});
}
+ ///
+ /// Returns true if the user is an admin or owner of an organization with unassigned ciphers (i.e. ciphers that
+ /// are not assigned to a collection).
+ ///
+ ///
+ [HttpGet("has-unassigned-ciphers")]
+ public async Task HasUnassignedCiphers()
+ {
+ var orgAbilities = await _applicationCacheService.GetOrganizationAbilitiesAsync();
+
+ var adminOrganizations = _currentContext.Organizations
+ .Where(o => o.Type is OrganizationUserType.Admin or OrganizationUserType.Owner &&
+ orgAbilities.ContainsKey(o.Id) && orgAbilities[o.Id].FlexibleCollections);
+
+ foreach (var org in adminOrganizations)
+ {
+ var unassignedCiphers = await _cipherRepository.GetManyUnassignedOrganizationDetailsByOrganizationIdAsync(org.Id);
+ // We only care about non-deleted ciphers
+ if (unassignedCiphers.Any(c => c.DeletedDate == null))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
private void ValidateAttachment()
{
if (!Request?.ContentType.Contains("multipart/") ?? true)
diff --git a/src/Core/Constants.cs b/src/Core/Constants.cs
index 8f5cc0773b..749419644a 100644
--- a/src/Core/Constants.cs
+++ b/src/Core/Constants.cs
@@ -132,6 +132,7 @@ public static class FeatureFlagKeys
public const string ShowPaymentMethodWarningBanners = "show-payment-method-warning-banners";
public const string EnableConsolidatedBilling = "enable-consolidated-billing";
public const string AC1795_UpdatedSubscriptionStatusSection = "AC-1795_updated-subscription-status-section";
+ public const string UnassignedItemsBanner = "unassigned-items-banner";
public static List GetAllKeys()
{