1
0
mirror of https://github.com/bitwarden/server synced 2026-02-05 03:03:42 +00:00

Merge branch 'main' into ac/pm-30610/fix-formatting

This commit is contained in:
Jimmy Vo
2026-01-21 11:33:38 -05:00
14 changed files with 750 additions and 463 deletions

View File

@@ -275,17 +275,24 @@ public class SubscriptionUpdatedHandler : ISubscriptionUpdatedHandler
.PreviousAttributes
.ToObject<Subscription>() as Subscription;
// Get all plan IDs that include Secrets Manager support to check if the organization has secret manager in the
// previous and/or current subscriptions.
var planIdsOfPlansWithSecretManager = (await _pricingClient.ListPlans())
.Where(orgPlan => orgPlan.SupportsSecretsManager && orgPlan.SecretsManager.StripeSeatPlanId != null)
.Select(orgPlan => orgPlan.SecretsManager.StripeSeatPlanId)
.ToHashSet();
// This being false doesn't necessarily mean that the organization doesn't subscribe to Secrets Manager.
// If there are changes to any subscription item, Stripe sends every item in the subscription, both
// changed and unchanged.
var previousSubscriptionHasSecretsManager =
previousSubscription?.Items is not null &&
previousSubscription.Items.Any(
previousSubscriptionItem => previousSubscriptionItem.Plan.Id == plan.SecretsManager.StripeSeatPlanId);
previousSubscriptionItem => planIdsOfPlansWithSecretManager.Contains(previousSubscriptionItem.Plan.Id));
var currentSubscriptionHasSecretsManager =
subscription.Items.Any(
currentSubscriptionItem => currentSubscriptionItem.Plan.Id == plan.SecretsManager.StripeSeatPlanId);
currentSubscriptionItem => planIdsOfPlansWithSecretManager.Contains(currentSubscriptionItem.Plan.Id));
if (!previousSubscriptionHasSecretsManager || currentSubscriptionHasSecretsManager)
{

View File

@@ -21,7 +21,9 @@ public interface IOrganizationRepository : IRepository<Organization, Guid>
Task<IEnumerable<string>> GetOwnerEmailAddressesById(Guid organizationId);
/// <summary>
/// Gets the organizations that have a verified domain matching the user's email domain.
/// Gets the organizations that have claimed the user's account. Currently, only one organization may claim a user.
/// This requires that the organization has claimed the user's domain and the user is an organization member.
/// It excludes invited members.
/// </summary>
Task<ICollection<Organization>> GetByVerifiedUserEmailDomainAsync(Guid userId);

View File

@@ -6,12 +6,52 @@
<mj-body css-class="border-fix">
<!-- Blue Header Section -->
<mj-wrapper css-class="border-fix" padding="20px 20px 10px 20px">
<mj-bw-hero
img-src="https://assets.bitwarden.com/email/v1/spot-family-homes.png"
title="You can now share passwords with members of <b>{{OrganizationName}}!</b>"
button-text="<b>Log in</b>"
button-url="{{WebVaultUrl}}"
/>
<mj-section
full-width="full-width"
background-color="#175ddc"
border-radius="4px 4px 0px 0px"
>
<mj-column width="70%">
<mj-image
align="left"
src="https://bitwarden.com/images/logo-horizontal-white.png"
width="150px"
height="30px"
/>
<mj-text color="#fff" padding-top="0" padding-bottom="0">
<h1 style="font-weight: normal; font-size: 24px; line-height: 32px">
You can now share passwords with members of <b>{{OrganizationName}}!</b>
</h1>
</mj-text>
<mj-button
href="{{WebVaultUrl}}"
background-color="#ffffff"
color="#1A41AC"
border-radius="20px"
align="left"
inner-padding="12px 24px"
font-size="16px"
font-family="Helvetica Neue, Helvetica, Arial, sans-serif"
font-weight="700"
line-height="24px"
>
Log in
</mj-button>
</mj-column>
<mj-column width="30%" vertical-align="bottom">
<mj-image
src="https://assets.bitwarden.com/email/v1/spot-family-homes.png"
alt=""
width="155px"
padding="0px"
css-class="mj-bw-hero-responsive-img"
/>
</mj-column>
</mj-section>
</mj-wrapper>
<!-- Main Content -->

View File

@@ -325,7 +325,8 @@ public class OrganizationRepository : Repository<Core.AdminConsole.Entities.Orga
where ou.UserId == userWithDomain.UserId &&
od.DomainName == userWithDomain.EmailDomain &&
od.VerifiedDate != null &&
o.Enabled == true
o.Enabled == true &&
ou.Status != OrganizationUserStatusType.Invited
select o;
return await query.ToArrayAsync();

View File

@@ -1,4 +1,5 @@
using Bit.Core.Entities;
using Bit.Core.Enums;
namespace Bit.Infrastructure.EntityFramework.Repositories.Queries;
@@ -16,6 +17,7 @@ public class OrganizationUserReadByClaimedOrganizationDomainsQuery : IQuery<Orga
var query = from ou in dbContext.OrganizationUsers
join u in dbContext.Users on ou.UserId equals u.Id
where ou.OrganizationId == _organizationId
&& ou.Status != OrganizationUserStatusType.Invited
&& dbContext.OrganizationDomains
.Any(od => od.OrganizationId == _organizationId &&
od.VerifiedDate != null &&

View File

@@ -8,13 +8,14 @@ BEGIN
SELECT *
FROM [dbo].[OrganizationUserView]
WHERE [OrganizationId] = @OrganizationId
AND [Status] != 0 -- Exclude invited users
),
UserDomains AS (
SELECT U.[Id], U.[EmailDomain]
FROM [dbo].[UserEmailDomainView] U
WHERE EXISTS (
SELECT 1
FROM [dbo].[OrganizationDomainView] OD
FROM [dbo].[OrganizationDomainView] OD
WHERE OD.[OrganizationId] = @OrganizationId
AND OD.[VerifiedDate] IS NOT NULL
AND OD.[DomainName] = U.[EmailDomain]

View File

@@ -6,7 +6,7 @@ BEGIN
WITH CTE_User AS (
SELECT
U.*,
U.[Id],
SUBSTRING(U.Email, CHARINDEX('@', U.Email) + 1, LEN(U.Email)) AS EmailDomain
FROM dbo.[UserView] U
WHERE U.[Id] = @UserId
@@ -19,4 +19,5 @@ BEGIN
WHERE OD.[VerifiedDate] IS NOT NULL
AND CU.EmailDomain = OD.[DomainName]
AND O.[Enabled] = 1
AND OU.[Status] != 0 -- Exclude invited users
END