Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[PM-15084] Push global notification creation to affected clients #5079

Open
wants to merge 5 commits into
base: km/pm-10564
Choose a base branch
from

Conversation

mzieniukbw
Copy link
Contributor

@mzieniukbw mzieniukbw commented Nov 25, 2024

🎟️ Tracking

https://bitwarden.atlassian.net/browse/PM-15084

This is Part 4.
See Part 3: #5057

📔 Objective

When a global notification is created via the service layer, distributes a “notification created” or "notification updated" push type event to related clients of the user.
Global notifications are sent to servers of the same installation id. All clients connected to any of the server instance of that installation id would receive it.
This is useful for notifying all clients of an installation about upcoming maintenance.
This works both for Self-Hosted, but also for Cloud (bitwarden.com), assuming an installation id is set.

📸 Screenshots

⏰ Reminders before review

  • Contributor guidelines followed
  • All formatters and local linters executed and passed
  • Written new unit and / or integration tests where applicable
  • Protected functional changes with optionality (feature flags)
  • Used internationalization (i18n) for all UI strings
  • CI builds passed
  • Communicated to DevOps any deployment requirements
  • Updated any necessary documentation (Confluence, contributing docs) or informed the documentation team

🦮 Reviewer guidelines

  • 👍 (:+1:) or similar for great changes
  • 📝 (:memo:) or ℹ️ (:information_source:) for notes or general info
  • ❓ (:question:) for questions
  • 🤔 (:thinking:) or 💭 (:thought_balloon:) for more open inquiry that's not quite a confirmed issue and could potentially benefit from discussion
  • 🎨 (:art:) for suggestions / improvements
  • ❌ (:x:) or ⚠️ (:warning:) for more significant problems or concerns needing attention
  • 🌱 (:seedling:) or ♻️ (:recycle:) for future improvements or indications of technical debt
  • ⛏ (:pick:) for minor or nitpick changes

This enables the Notification Center created global notifications to be sent to affected devices of the same server installation. All clients connected to any of the server instance of that installation id would receive it.
This is useful for notifying all clients of an installation about upcoming maintenance.
This works both for Self-Hosted, but also for Cloud, assuming an installation id is set.
@mzieniukbw mzieniukbw requested a review from a team as a code owner November 25, 2024 18:15
@mzieniukbw mzieniukbw changed the base branch from main to km/pm-10600 November 25, 2024 18:15
@mzieniukbw mzieniukbw changed the base branch from km/pm-10600 to km/pm-10564 November 25, 2024 18:16
@mzieniukbw mzieniukbw requested review from a team, withinfocus and MGibson1 and removed request for a team and Patrick-Pimentel-Bitwarden November 25, 2024 18:16
Copy link

codecov bot commented Nov 25, 2024

Codecov Report

Attention: Patch coverage is 50.00000% with 92 lines in your changes missing coverage. Please review.

Project coverage is 43.42%. Comparing base (28ff53c) to head (7b4122c).

Files with missing lines Patch % Lines
...es/Implementations/RelayPushNotificationService.cs 0.00% 32 Missing ⚠️
src/Notifications/NotificationsHub.cs 0.00% 25 Missing ⚠️
src/Notifications/HubHelpers.cs 0.00% 17 Missing ⚠️
...tations/NotificationsApiPushNotificationService.cs 0.00% 6 Missing ⚠️
...ationHub/NotificationHubPushNotificationService.cs 90.00% 3 Missing and 1 partial ⚠️
...SharedWeb/Utilities/ServiceCollectionExtensions.cs 0.00% 4 Missing ⚠️
...es/Implementations/RelayPushRegistrationService.cs 0.00% 2 Missing ⚠️
...plementations/AzureQueuePushNotificationService.cs 87.50% 1 Missing ⚠️
...NoopImplementations/NoopPushNotificationService.cs 0.00% 1 Missing ⚠️
Additional details and impacted files
@@               Coverage Diff               @@
##           km/pm-10564    #5079      +/-   ##
===============================================
+ Coverage        43.34%   43.42%   +0.08%     
===============================================
  Files             1412     1412              
  Lines            65030    65161     +131     
  Branches          5940     5963      +23     
===============================================
+ Hits             28184    28299     +115     
- Misses           35608    35622      +14     
- Partials          1238     1240       +2     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link
Contributor

github-actions bot commented Nov 25, 2024

Logo
Checkmarx One – Scan Summary & Details28739fd2-50f5-4fac-aef5-6119eee7a113

New Issues

Severity Issue Source File / Package Checkmarx Insight
MEDIUM CSRF /src/Api/Controllers/PushController.cs: 47 Attack Vector
LOW Log_Forging /src/Api/Controllers/PushController.cs: 72 Attack Vector

Fixed Issues

Severity Issue Source File / Package
MEDIUM CSRF /src/Api/Controllers/PushController.cs: 38
MEDIUM CSRF /src/Identity/Controllers/AccountsController.cs: 76
MEDIUM CSRF /src/Api/Controllers/PushController.cs: 38
MEDIUM CSRF /src/Api/Controllers/PushController.cs: 38
LOW Log_Forging /src/Api/Controllers/PushController.cs: 71

# Conflicts:
#	src/Core/Models/PushNotification.cs
#	src/Core/NotificationHub/NotificationHubPushNotificationService.cs
#	src/Core/Services/Implementations/AzureQueuePushNotificationService.cs
#	src/Core/Services/Implementations/NotificationsApiPushNotificationService.cs
#	src/Core/Services/Implementations/RelayPushNotificationService.cs
#	src/Core/Services/NoopImplementations/NoopPushNotificationService.cs
#	test/Core.Test/NotificationHub/NotificationHubPushNotificationServiceTests.cs
#	test/Core.Test/Services/AzureQueuePushNotificationServiceTests.cs
Renamed PushType's `SyncNotification` to `Notification`, since the push type payload does not require, is not dependent on the sync mechanism.
Copy link
Contributor

@Thomas-Avery Thomas-Avery left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good, a few things to take a look at.

Title = notification.Title,
Body = notification.Body,
CreationDate = notification.CreationDate,
RevisionDate = notification.RevisionDate
};

if (notification.UserId.HasValue)
if (notification.Global && installationId.HasValue)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💭 Should there be some logging or an exception thrown if none of these conditions are met?

This is applicable to the other services with the same logic.

@@ -228,15 +252,20 @@ public async Task PushNotificationStatusAsync(Notification notification, Notific
DeletedDate = notificationStatus.DeletedDate
};

if (notification.UserId.HasValue)
if (notification.Global && installationId.HasValue)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here. Should there be some logging or an exception thrown if none of these conditions are met?


namespace Bit.Test.Common.AutoFixture.Attributes;

public class RepeatingPatternBitAutoDataAttribute : BitAutoDataAttribute
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💭
I really like the idea of what we're trying to solve here. It's annoying to type out and easy to miss some of those inline data sets.

I think it would have been easier to have this in a separate PR, since it's introducing a new testing tool/attribute.

Xunit has a few different solutions with their idea of sharing test data ClassData MemberData and I know there are a few libraries that similarly do what you have proposed.

For this specifically, I think combining xUnit's idea of ClassData with BitAutoData is an alternative to consider here.

Something like (this is rough code could be cleaned up)

  public class ClassBitAutoDataAttribute : BitAutoDataAttribute
    {
        public ClassBitAutoDataAttribute(Type @class)
        {
            Class = @class;
        }

        public Type Class { get; private set; }

        public override IEnumerable<object[]> GetData(MethodInfo testMethod)
        {
            IEnumerable<object[]> data = Activator.CreateInstance(Class) as IEnumerable<object[]>;
            if (data == null)
            {
                throw new ArgumentException(
                    string.Format(
                        CultureInfo.CurrentCulture,
                        "{0} must implement IEnumerable<object[]> to be used as ClassData for the test method named '{1}' on {2}",
                        Class.FullName,
                        testMethod.Name,
                        testMethod.DeclaringType.FullName
                    )
                );
            }

            foreach (var classData in data)
            {
                var bitData = base.GetData(testMethod).First();
                for (var i = 0; i < classData.Length; i++)
                {
                    bitData[i] = classData[i];
                }

                yield return bitData;
            }
        }
    }

Then we could have one class to share data across tests

   public class SendAsyncTestData : TheoryData<bool, bool, bool>
    {
        public SendAsyncTestData()
        {
            Add(false, false, false);
            Add(true, false, false);
            Add(false, true, false);
            Add(true, true, false);
            Add(false, false, true);
            Add(true, false, true);
            Add(false, true, true);
        }
    };

Usage in an individual test.

    [Theory]
    [ClassBitAutoDataAttribute(typeof(SendAsyncTestData))]
    public async Task SendAsync_UserIdSet_SendPayloadToUserAsync(bool haveIdentifier, bool haveDeviceId,
        bool haveOrganizationId, SutProvider<PushController> sutProvider, Guid installationId, Guid userId,
        Guid identifier, Guid deviceId)
    {

This would give us more flexibility and allow for generating (looping through combinations) the test data within the test data class if required.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants